物联设备摄像头拖动旋转
This commit is contained in:
parent
cdeae7e53e
commit
54b36c45a7
|
|
@ -2,7 +2,10 @@
|
|||
<!-- <a-spin :spinning="confirmLoading">-->
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<div id="video-container-preview" style="min-height: 400px;"></div>
|
||||
<div id="video-container-preview" style="min-height: 400px;"
|
||||
@mousedown="onCameraMouseDown" @mousemove="onCameraMouseMove" @mouseup="onCameraMouseUp"
|
||||
@mouseleave="onCameraMouseLeave" @wheel="onCameraWheel" @contextmenu.prevent
|
||||
></div>
|
||||
<div id="videview" style="height:0px;"></div>
|
||||
</a-col>
|
||||
<!-- <a-col :span="24" style="margin-top: -120px;margin-left:40px;" v-show="formData.ptz == '1'"> -->
|
||||
|
|
@ -460,18 +463,18 @@ function zoomInOut(type) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制球机
|
||||
*/
|
||||
function moveCtrl(direction, startOrNot, speed) {
|
||||
let params = {
|
||||
"deviceIndex": formData.deviceIndex,
|
||||
"direction": direction,
|
||||
"startOrNot": startOrNot,
|
||||
"speed": speed,
|
||||
};
|
||||
motionCtrl(params);
|
||||
}
|
||||
// /**
|
||||
// * 控制球机
|
||||
// */
|
||||
// function moveCtrl(direction, startOrNot, speed) {
|
||||
// let params = {
|
||||
// "deviceIndex": formData.deviceIndex,
|
||||
// "direction": direction,
|
||||
// "startOrNot": startOrNot,
|
||||
// "speed": speed,
|
||||
// };
|
||||
// motionCtrl(params);
|
||||
// }
|
||||
|
||||
function delayExecute(fn, args, delay) {
|
||||
setTimeout(() => {
|
||||
|
|
@ -490,6 +493,345 @@ function destroy() {
|
|||
}
|
||||
}
|
||||
|
||||
//控制画面移动
|
||||
const isDragging = ref(false) // 是否正在拖动
|
||||
const dragStartPos = ref({ x: 0, y: 0 }) // 拖动开始位置
|
||||
const dragTimer = ref<any>(null) // 拖动计时器
|
||||
const moveDirection = ref<number | null>(null) // 移动方向
|
||||
const moveCalled = ref(false) // 是否已调用move方法
|
||||
const lastMousePos = ref({ x: 0, y: 0 }) // 最后一次鼠标位置
|
||||
const moveSamples = ref<Array<{ x: number, y: number, t: number }>>([]) // 移动采样点
|
||||
const moveStartTime = ref<number>(0) // 移动开始时间
|
||||
const zoomTimer = ref<any>(null) // 滚轮计时器
|
||||
const isZooming = ref(false) // 是否正在缩放
|
||||
const zoomDirection = ref<number | null>(null) // 缩放方向
|
||||
const lastWheelTime = ref<number>(0) // 最后滚轮时间
|
||||
|
||||
/**
|
||||
* 控制球机移动
|
||||
*/
|
||||
function moveCtrl(direction, startOrNot, speed) {
|
||||
if (!formData.deviceIndex) return;
|
||||
|
||||
let params = {
|
||||
"deviceIndex": formData.deviceIndex,
|
||||
"direction": direction,
|
||||
"startOrNot": startOrNot,
|
||||
"speed": speed,
|
||||
};
|
||||
motionCtrl(params);
|
||||
|
||||
if (startOrNot === 1) {
|
||||
const directions = {
|
||||
1: '上',
|
||||
3: '左',
|
||||
5: '右',
|
||||
7: '下',
|
||||
9: '缩小',
|
||||
10: '放大',
|
||||
11: '对焦'
|
||||
};
|
||||
const action = startOrNot === 1 ? '开始' : '停止';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标在摄像头上按下
|
||||
*/
|
||||
function onCameraMouseDown(e: MouseEvent) {
|
||||
// 只响应左键
|
||||
if (e.button !== 0) return
|
||||
|
||||
isDragging.value = true
|
||||
moveCalled.value = false
|
||||
moveDirection.value = null
|
||||
moveSamples.value = [] // 清空采样点
|
||||
moveStartTime.value = Date.now()
|
||||
|
||||
// 记录起点位置
|
||||
const startPos = {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
t: Date.now()
|
||||
}
|
||||
dragStartPos.value = { x: startPos.x, y: startPos.y }
|
||||
lastMousePos.value = { x: e.clientX, y: e.clientY } // 记录当前鼠标位置
|
||||
moveSamples.value.push(startPos) // 记录第一个采样点
|
||||
|
||||
// 设置0.5秒计时器
|
||||
if (dragTimer.value) {
|
||||
clearTimeout(dragTimer.value)
|
||||
}
|
||||
dragTimer.value = setTimeout(() => {
|
||||
if (isDragging.value && !moveCalled.value && moveSamples.value.length > 1) {
|
||||
determineMoveDirection()
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标在摄像头上移动
|
||||
*/
|
||||
function onCameraMouseMove(e: MouseEvent) {
|
||||
if (!isDragging.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 记录当前鼠标位置
|
||||
lastMousePos.value = { x: e.clientX, y: e.clientY }
|
||||
|
||||
// 记录当前移动点
|
||||
const currentPos = {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
t: Date.now()
|
||||
}
|
||||
moveSamples.value.push(currentPos)
|
||||
|
||||
// 只保留最近20个点
|
||||
if (moveSamples.value.length > 20) {
|
||||
moveSamples.value = moveSamples.value.slice(-20)
|
||||
}
|
||||
|
||||
|
||||
// 如果已经调用过move,就不重复调用
|
||||
if (moveCalled.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 计算移动距离
|
||||
const moveX = e.clientX - dragStartPos.value.x
|
||||
const moveY = e.clientY - dragStartPos.value.y
|
||||
const distance = Math.sqrt(moveX * moveX + moveY * moveY)
|
||||
|
||||
|
||||
// 判断是否移动足够距离(防止微小抖动误判)
|
||||
const minMove = 5 // 最小移动距离
|
||||
if (distance < minMove) {
|
||||
return
|
||||
}
|
||||
|
||||
// 清除计时器
|
||||
if (dragTimer.value) {
|
||||
clearTimeout(dragTimer.value)
|
||||
dragTimer.value = null
|
||||
}
|
||||
|
||||
// 根据方向调用移动
|
||||
determineMoveDirection()
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断移动方向
|
||||
*/
|
||||
function determineMoveDirection() {
|
||||
if (!isDragging.value || moveCalled.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取起点和当前鼠标位置
|
||||
const startPos = dragStartPos.value
|
||||
const endPos = lastMousePos.value
|
||||
|
||||
const deltaX = endPos.x - startPos.x
|
||||
const deltaY = endPos.y - startPos.y
|
||||
const absDeltaX = Math.abs(deltaX)
|
||||
const absDeltaY = Math.abs(deltaY)
|
||||
|
||||
|
||||
// 设置角度阈值(判断斜对角方向)
|
||||
const angleThreshold = Math.PI / 6 // 30度
|
||||
|
||||
// 计算角度
|
||||
const angle = Math.atan2(deltaY, deltaX)
|
||||
const absAngle = Math.abs(angle)
|
||||
|
||||
|
||||
let direction: number
|
||||
|
||||
// 判断8个方向
|
||||
if (absDeltaX < 5 && absDeltaY < 5) {
|
||||
// 移动距离太小,不处理
|
||||
return
|
||||
}
|
||||
|
||||
// 判断方向
|
||||
if (absAngle < angleThreshold) {
|
||||
// 右: 0度附近
|
||||
direction = 5
|
||||
} else if (absAngle > Math.PI - angleThreshold) {
|
||||
// 左: ±180度附近
|
||||
direction = 3
|
||||
} else if (angle > 0) {
|
||||
// 下半部分
|
||||
if (absAngle < Math.PI / 2 - angleThreshold) {
|
||||
// 右下: 45度附近
|
||||
direction = 8
|
||||
} else if (absAngle > Math.PI / 2 + angleThreshold) {
|
||||
// 左下: 135度附近
|
||||
direction = 6
|
||||
} else {
|
||||
// 下: 90度附近
|
||||
direction = 7
|
||||
}
|
||||
} else {
|
||||
// 上半部分
|
||||
if (absAngle < Math.PI / 2 - angleThreshold) {
|
||||
// 右上: -45度附近
|
||||
direction = 2
|
||||
} else if (absAngle > Math.PI / 2 + angleThreshold) {
|
||||
// 左上: -135度附近
|
||||
direction = 0
|
||||
} else {
|
||||
// 上: -90度附近
|
||||
direction = 1
|
||||
}
|
||||
}
|
||||
|
||||
// 记录方向
|
||||
moveDirection.value = direction
|
||||
moveCalled.value = true
|
||||
|
||||
// 调用开始移动
|
||||
moveCtrl(direction, 1, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标在摄像头上松开
|
||||
*/
|
||||
function onCameraMouseUp(e: MouseEvent) {
|
||||
if (!isDragging.value) return
|
||||
|
||||
// 清除计时器
|
||||
if (dragTimer.value) {
|
||||
clearTimeout(dragTimer.value)
|
||||
dragTimer.value = null
|
||||
}
|
||||
|
||||
// 如果有正在进行的移动,调用结束
|
||||
if (moveDirection.value !== null) {
|
||||
moveCtrl(moveDirection.value, 0, 1)
|
||||
} else {
|
||||
}
|
||||
|
||||
// 记录数据用于分析
|
||||
if (moveSamples.value.length > 0) {
|
||||
const firstPoint = moveSamples.value[0]
|
||||
const lastPoint = moveSamples.value[moveSamples.value.length - 1]
|
||||
const totalDistance = Math.sqrt(
|
||||
Math.pow(lastPoint.x - firstPoint.x, 2) +
|
||||
Math.pow(lastPoint.y - firstPoint.y, 2)
|
||||
)
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
isDragging.value = false
|
||||
moveCalled.value = false
|
||||
moveDirection.value = null
|
||||
moveSamples.value = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标滚轮事件
|
||||
*/
|
||||
function onCameraWheel(e: WheelEvent) {
|
||||
// 防止页面滚动
|
||||
e.preventDefault()
|
||||
|
||||
const now = Date.now()
|
||||
const deltaY = e.deltaY // 滚轮滚动量
|
||||
|
||||
console.log("🔄 滚轮滚动:", deltaY)
|
||||
|
||||
// 判断滚轮方向
|
||||
// deltaY > 0: 向下滚动(缩小)
|
||||
// deltaY < 0: 向上滚动(放大)
|
||||
const direction = deltaY > 0 ? 9 : 10
|
||||
|
||||
// 如果正在缩放,先结束之前的缩放
|
||||
if (isZooming.value) {
|
||||
// 如果方向相同,继续当前缩放
|
||||
if (zoomDirection.value === direction) {
|
||||
// 重置1秒计时器
|
||||
if (zoomTimer.value) {
|
||||
clearTimeout(zoomTimer.value)
|
||||
}
|
||||
zoomTimer.value = setTimeout(() => {
|
||||
endZoom()
|
||||
}, 1000)
|
||||
lastWheelTime.value = now
|
||||
return
|
||||
} else {
|
||||
// 方向改变,先结束当前缩放
|
||||
endZoom()
|
||||
}
|
||||
}
|
||||
|
||||
// 开始新的缩放
|
||||
startZoom(direction)
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始缩放
|
||||
*/
|
||||
function startZoom(direction: number) {
|
||||
console.log("🔍 开始缩放:", direction === 9 ? '缩小' : '放大')
|
||||
|
||||
isZooming.value = true
|
||||
zoomDirection.value = direction
|
||||
|
||||
// 调用开始缩放
|
||||
moveCtrl(direction, 1, 1)
|
||||
|
||||
// 设置1秒后自动结束
|
||||
if (zoomTimer.value) {
|
||||
clearTimeout(zoomTimer.value)
|
||||
}
|
||||
zoomTimer.value = setTimeout(() => {
|
||||
endZoom()
|
||||
}, 1000)
|
||||
|
||||
lastWheelTime.value = Date.now()
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束缩放
|
||||
*/
|
||||
function endZoom() {
|
||||
if (isZooming.value && zoomDirection.value !== null) {
|
||||
console.log("🛑 结束缩放:", zoomDirection.value === 9 ? '缩小' : '放大')
|
||||
moveCtrl(zoomDirection.value, 0, 1)
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
isZooming.value = false
|
||||
zoomDirection.value = null
|
||||
|
||||
if (zoomTimer.value) {
|
||||
clearTimeout(zoomTimer.value)
|
||||
zoomTimer.value = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理滚轮计时器
|
||||
*/
|
||||
function clearZoomTimer() {
|
||||
if (zoomTimer.value) {
|
||||
clearTimeout(zoomTimer.value)
|
||||
zoomTimer.value = null
|
||||
}
|
||||
isZooming.value = false
|
||||
zoomDirection.value = null
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标离开摄像头区域
|
||||
*/
|
||||
function onCameraMouseLeave(e: MouseEvent) {
|
||||
onCameraMouseUp(e)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
edit,
|
||||
destroy
|
||||
|
|
|
|||
|
|
@ -95,6 +95,11 @@ export const dictItemColumns: BasicColumn[] = [
|
|||
dataIndex: 'itemValue',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'description',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '字典颜色',
|
||||
dataIndex: 'itemColor',
|
||||
|
|
|
|||
Loading…
Reference in New Issue