物联设备摄像头拖动旋转

This commit is contained in:
曹磊 2026-03-17 14:02:31 +08:00
parent cdeae7e53e
commit 54b36c45a7
2 changed files with 360 additions and 13 deletions

View File

@ -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

View File

@ -95,6 +95,11 @@ export const dictItemColumns: BasicColumn[] = [
dataIndex: 'itemValue',
width: 80,
},
{
title: '描述',
dataIndex: 'description',
width: 100,
},
{
title: '字典颜色',
dataIndex: 'itemColor',