物联设备摄像头拖动旋转
This commit is contained in:
parent
cdeae7e53e
commit
54b36c45a7
|
|
@ -2,7 +2,10 @@
|
||||||
<!-- <a-spin :spinning="confirmLoading">-->
|
<!-- <a-spin :spinning="confirmLoading">-->
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="24">
|
<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>
|
<div id="videview" style="height:0px;"></div>
|
||||||
</a-col>
|
</a-col>
|
||||||
<!-- <a-col :span="24" style="margin-top: -120px;margin-left:40px;" v-show="formData.ptz == '1'"> -->
|
<!-- <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) {
|
// function moveCtrl(direction, startOrNot, speed) {
|
||||||
let params = {
|
// let params = {
|
||||||
"deviceIndex": formData.deviceIndex,
|
// "deviceIndex": formData.deviceIndex,
|
||||||
"direction": direction,
|
// "direction": direction,
|
||||||
"startOrNot": startOrNot,
|
// "startOrNot": startOrNot,
|
||||||
"speed": speed,
|
// "speed": speed,
|
||||||
};
|
// };
|
||||||
motionCtrl(params);
|
// motionCtrl(params);
|
||||||
}
|
// }
|
||||||
|
|
||||||
function delayExecute(fn, args, delay) {
|
function delayExecute(fn, args, delay) {
|
||||||
setTimeout(() => {
|
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({
|
defineExpose({
|
||||||
edit,
|
edit,
|
||||||
destroy
|
destroy
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,11 @@ export const dictItemColumns: BasicColumn[] = [
|
||||||
dataIndex: 'itemValue',
|
dataIndex: 'itemValue',
|
||||||
width: 80,
|
width: 80,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'description',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '字典颜色',
|
title: '字典颜色',
|
||||||
dataIndex: 'itemColor',
|
dataIndex: 'itemColor',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue