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

View File

@ -41,15 +41,15 @@
<div class="dpad"> <div class="dpad">
<button class="dpad__btn dpad__btn--up" <button class="dpad__btn dpad__btn--up"
@mousedown="onPress('forward')" @mouseup="onRelease" @mouseleave="onRelease" @pointerdown="onPointerDown($event, 'forward')"
@touchstart.prevent="onPress('forward')" @touchend.prevent="onRelease"> @pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M7 1L13 11H1Z" fill="currentColor" /></svg> <svg viewBox="0 0 14 14"><path d="M7 1L13 11H1Z" fill="currentColor" /></svg>
<small>前进</small> <small>前进</small>
</button> </button>
<button class="dpad__btn dpad__btn--lt" <button class="dpad__btn dpad__btn--lt"
@mousedown="onPress('left')" @mouseup="onRelease" @pointerdown="onPointerDown($event, 'left')"
@touchstart.prevent="onPress('left')" @touchend.prevent="onRelease"> @pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M1 7L11 1V13Z" fill="currentColor" /></svg> <svg viewBox="0 0 14 14"><path d="M1 7L11 1V13Z" fill="currentColor" /></svg>
<small>左转</small> <small>左转</small>
</button> </button>
@ -57,15 +57,15 @@
<div class="dpad__core"><span /></div> <div class="dpad__core"><span /></div>
<button class="dpad__btn dpad__btn--rt" <button class="dpad__btn dpad__btn--rt"
@mousedown="onPress('right')" @mouseup="onRelease" @pointerdown="onPointerDown($event, 'right')"
@touchstart.prevent="onPress('right')" @touchend.prevent="onRelease"> @pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M13 7L3 1V13Z" fill="currentColor" /></svg> <svg viewBox="0 0 14 14"><path d="M13 7L3 1V13Z" fill="currentColor" /></svg>
<small>右转</small> <small>右转</small>
</button> </button>
<button class="dpad__btn dpad__btn--dn" <button class="dpad__btn dpad__btn--dn"
@mousedown="onPress('backward')" @mouseup="onRelease" @pointerdown="onPointerDown($event, 'backward')"
@touchstart.prevent="onPress('backward')" @touchend.prevent="onRelease"> @pointerup="onPointerEnd" @pointercancel="onPointerEnd">
<svg viewBox="0 0 14 14"><path d="M7 13L1 3H13Z" fill="currentColor" /></svg> <svg viewBox="0 0 14 14"><path d="M7 13L1 3H13Z" fill="currentColor" /></svg>
<small>后退</small> <small>后退</small>
</button> </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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -364,6 +401,8 @@ function onRelease() {
color: $color-text-primary; color: $color-text-primary;
cursor: pointer; cursor: pointer;
transition: all .15s ease; transition: all .15s ease;
touch-action: none;
-webkit-user-select: none;
svg { svg {
width: 14px; width: 14px;