feat: 调整事件

This commit is contained in:
zhanghao 2026-07-21 15:57:47 +08:00
parent 571bfa2552
commit 498e165713
2 changed files with 112 additions and 36 deletions

View File

@ -50,14 +50,14 @@
<label :for="joint.name">{{ joint.name }}</label>
<el-input v-model="joint.value" readonly>
<template #prepend>
<el-button @mousedown="updateJoint(joint.name, '-')" @mouseup="stop"
@touchstart.prevent="updateJoint(joint.name, '-')" @touchend.prevent="stop">
<el-button class="press-control" @pointerdown="startPointerControl($event, () => updateJoint(joint.name, '-'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
-
</el-button>
</template>
<template #append>
<el-button @mousedown="updateJoint(joint.name, '+')" @mouseup="stop"
@touchstart.prevent="updateJoint(joint.name, '+')" @touchend.prevent="stop">
<el-button class="press-control" @pointerdown="startPointerControl($event, () => updateJoint(joint.name, '+'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
+
</el-button>
</template>
@ -94,14 +94,14 @@
<div class="axis-slider-wrap">
<div class="axis-name">前后平移</div>
<div>
<el-button type="primary" circle @mousedown="move('x', '-', 'end')" @mouseup="stop"
@touchstart.prevent="move('x', '-')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('x', '-', 'end'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<Remove />
</el-icon>
</el-button>
<el-button type="primary" circle @mousedown="move('x', '+', 'end')" @mouseup="stop"
@touchstart.prevent="move('x', '+')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('x', '+', 'end'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<CirclePlus />
</el-icon>
@ -116,14 +116,14 @@
<div class="axis-slider-wrap">
<div class="axis-name">左右平移</div>
<div>
<el-button type="primary" circle @mousedown="move('y', '-', 'end')" @mouseup="stop"
@touchstart.prevent="move('y', '-')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('y', '-', 'end'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<Remove />
</el-icon>
</el-button>
<el-button type="primary" circle @mousedown="move('y', '+', 'end')" @mouseup="stop"
@touchstart.prevent="move('y', '+')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('y', '+', 'end'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<CirclePlus />
</el-icon>
@ -138,14 +138,14 @@
<div class="axis-slider-wrap">
<div class="axis-name">上下平移</div>
<div>
<el-button type="primary" circle @mousedown="move('z', '-', 'end')" @mouseup="stop"
@touchstart.prevent="move('z', '-')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('z', '-', 'end'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<Remove />
</el-icon>
</el-button>
<el-button type="primary" circle @mousedown="move('z', '+', 'end')" @mouseup="stop"
@touchstart.prevent="move('z', '+')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('z', '+', 'end'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<CirclePlus />
</el-icon>
@ -170,14 +170,14 @@
<div class="axis-slider-wrap">
<div class="axis-name">前后平移</div>
<div>
<el-button type="primary" circle @mousedown="move('x', '-', 'posture')" @mouseup="stop"
@touchstart.prevent="move('x', '-')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('x', '-', 'posture'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<Remove />
</el-icon>
</el-button>
<el-button type="primary" circle @mousedown="move('x', '+', 'posture')" @mouseup="stop"
@touchstart.prevent="move('x', '+')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('x', '+', 'posture'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<CirclePlus />
</el-icon>
@ -192,14 +192,14 @@
<div class="axis-slider-wrap">
<div class="axis-name">左右平移</div>
<div>
<el-button type="primary" circle @mousedown="move('y', '-', 'posture')" @mouseup="stop"
@touchstart.prevent="move('y', '-')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('y', '-', 'posture'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<Remove />
</el-icon>
</el-button>
<el-button type="primary" circle @mousedown="move('y', '+', 'posture')" @mouseup="stop"
@touchstart.prevent="move('y', '+')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('y', '+', 'posture'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<CirclePlus />
</el-icon>
@ -214,14 +214,14 @@
<div class="axis-slider-wrap">
<div class="axis-name">上下平移</div>
<div>
<el-button type="primary" circle @mousedown="move('z', '-', 'posture')" @mouseup="stop"
@touchstart.prevent="move('z', '-')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('z', '-', 'posture'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<Remove />
</el-icon>
</el-button>
<el-button type="primary" circle @mousedown="move('z', '+', 'posture')" @mouseup="stop"
@touchstart.prevent="move('z', '+')" @touchend.prevent="stop">
<el-button class="press-control" type="primary" circle @pointerdown="startPointerControl($event, () => move('z', '+', 'posture'))"
@pointerup="endPointerControl" @pointercancel="endPointerControl">
<el-icon size="24">
<CirclePlus />
</el-icon>
@ -410,8 +410,37 @@ const stop = async () => {
})
}
const activePointerIds = new Set()
const startPointerControl = (event, action) => {
if (event.pointerType === 'mouse' && event.button !== 0) return
event.preventDefault()
activePointerIds.add(event.pointerId)
event.currentTarget?.setPointerCapture?.(event.pointerId)
action()
}
const endPointerControl = (event) => {
event.preventDefault()
if (!activePointerIds.has(event.pointerId)) return
activePointerIds.delete(event.pointerId)
if (event.currentTarget?.hasPointerCapture?.(event.pointerId)) {
event.currentTarget.releasePointerCapture(event.pointerId)
}
stop()
}
const stopActiveControls = () => {
if (!activePointerIds.size) return
activePointerIds.clear()
stop()
}
const timer = ref(null)
onMounted(() => {
window.addEventListener('blur', stopActiveControls)
nextTick(() => {
jointControls.value = urdfViewerRef.value.jointControls
torqueOn()
@ -427,6 +456,8 @@ onMounted(() => {
})
onUnmounted(() => {
window.removeEventListener('blur', stopActiveControls)
stopActiveControls()
if (timer.value) {
clearInterval(timer.value)
}
@ -443,6 +474,12 @@ onUnmounted(() => {
overflow: hidden;
user-select: none;
.press-control {
touch-action: none;
-webkit-user-select: none;
user-select: none;
}
//
.main-wrap {
width: 100%;

View File

@ -41,15 +41,15 @@
<div class="dpad">
<button class="dpad__btn dpad__btn--up"
@mousedown="onPress('forward')" @mouseup="onRelease" @mouseleave="onRelease"
@touchstart.prevent="onPress('forward')" @touchend.prevent="onRelease">
@pointerdown="onPointerDown($event, 'forward')"
@pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M7 1L13 11H1Z" fill="currentColor" /></svg>
<small>前进</small>
</button>
<button class="dpad__btn dpad__btn--lt"
@mousedown="onPress('left')" @mouseup="onRelease"
@touchstart.prevent="onPress('left')" @touchend.prevent="onRelease">
@pointerdown="onPointerDown($event, 'left')"
@pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M1 7L11 1V13Z" fill="currentColor" /></svg>
<small>左转</small>
</button>
@ -57,15 +57,15 @@
<div class="dpad__core"><span /></div>
<button class="dpad__btn dpad__btn--rt"
@mousedown="onPress('right')" @mouseup="onRelease"
@touchstart.prevent="onPress('right')" @touchend.prevent="onRelease">
@pointerdown="onPointerDown($event, 'right')"
@pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M13 7L3 1V13Z" fill="currentColor" /></svg>
<small>右转</small>
</button>
<button class="dpad__btn dpad__btn--dn"
@mousedown="onPress('backward')" @mouseup="onRelease"
@touchstart.prevent="onPress('backward')" @touchend.prevent="onRelease">
@pointerdown="onPointerDown($event, 'backward')"
@pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M7 13L1 3H13Z" fill="currentColor" /></svg>
<small>后退</small>
</button>
@ -200,6 +200,43 @@ function onRelease() {
})
}
const activePointerIds = new Set()
const onPointerDown = (event, direction) => {
if (event.pointerType === 'mouse' && event.button !== 0) return
event.preventDefault()
activePointerIds.add(event.pointerId)
event.currentTarget?.setPointerCapture?.(event.pointerId)
onPress(direction)
}
const onPointerEnd = (event) => {
event.preventDefault()
if (!activePointerIds.has(event.pointerId)) return
activePointerIds.delete(event.pointerId)
if (event.currentTarget?.hasPointerCapture?.(event.pointerId)) {
event.currentTarget.releasePointerCapture(event.pointerId)
}
onRelease()
}
const releaseActivePointers = () => {
if (!activePointerIds.size) return
activePointerIds.clear()
onRelease()
}
onMounted(() => {
window.addEventListener('blur', releaseActivePointers)
})
onBeforeUnmount(() => {
window.removeEventListener('blur', releaseActivePointers)
releaseActivePointers()
})
</script>
<style lang="scss" scoped>
@ -364,6 +401,8 @@ function onRelease() {
color: $color-text-primary;
cursor: pointer;
transition: all .15s ease;
touch-action: none;
-webkit-user-select: none;
svg {
width: 14px;