Browse Source

EsDragControl 延迟抓取

master
修宁 6 months ago
parent
commit
d3ade02a95
  1. 82
      src/core/controls/DragControl.ts

82
src/core/controls/DragControl.ts

@ -11,24 +11,34 @@ export default class DragControl implements IControls {
private viewport: Viewport
private _is_enabled: boolean = true
private domElement: HTMLElement
public isDragging: boolean = false
private isPointerDown: boolean = false
private dragStartMouse: THREE.Vector2 = new THREE.Vector2()
private checkStateInterval: number | null = null
private dragShadowsGroup: THREE.Group | null = null
private dragDelayTimeout: number | null = null
private static readonly SHADOW_MATERIAL = new THREE.MeshBasicMaterial({
color: 0x222222,
transparent: true,
opacity: 0.5,
depthWrite: false,
side: THREE.DoubleSide
})
public isDragging: boolean = false
init(viewport: Viewport): void {
this.viewport = viewport
const domElement = this.viewport.renderer.domElement
this.domElement = domElement
domElement.addEventListener('pointerdown', this.onPointerDown)
domElement.addEventListener('pointermove', this.onPointerMove)
domElement.addEventListener('pointerup', this.onPointerUp)
domElement.addEventListener('pointerleave', this.onPointerLeave)
domElement.style.cursor = 'auto'
this.domElement = domElement
}
@ -41,12 +51,10 @@ export default class DragControl implements IControls {
this.domElement.removeEventListener('pointerdown', this.onPointerDown)
this.domElement.removeEventListener('pointerup', this.onPointerUp)
this.domElement.removeEventListener('pointerleave', this.onPointerLeave)
this.cleanupDrag()
this.domElement.style.cursor = 'auto'
this.viewport = null
}
this.cleanupDrag()
this.viewport = null
}
/**
@ -57,35 +65,29 @@ export default class DragControl implements IControls {
const mouse = this.getMousePosition(event.clientX, event.clientY)
const intersected = this.getIntersectedDraggableObject(mouse)
if (!intersected) return
this.viewport.controls.enabled = false
// 设置定时器:0.1秒后才抓取拖拽
this.dragDelayTimeout = window.setTimeout(() => {
const mouse = this.getMousePosition(event.clientX, event.clientY)
const intersected = this.getIntersectedDraggableObject(mouse)
if (!intersected) return
this.isPointerDown = true
this.dragStartMouse.set(intersected.position.x, intersected.position.z)
let selectedObjects = [intersected]
if (this.viewport.state.multiSelectedObjects.length > 0) {
if (this.viewport.state.multiSelectedObjects.includes(intersected)) {
// drag multi-selected objects
selectedObjects = this.viewport.state.multiSelectedObjects
}
const multiSelected = this.viewport.state.multiSelectedObjects
if (multiSelected.length > 0 && multiSelected.includes(intersected)) {
selectedObjects = multiSelected
}
this.createShadows(selectedObjects)
this.domElement.style.cursor = 'grabbing'
this.checkStateInterval = setInterval(() => {
if (isNaN(CurrentMouseInfo.x) || isNaN(CurrentMouseInfo.z) || !this.isPointerDown) {
this.cancelDrag()
}
}, 100)
this.createShadows(selectedObjects)
this.domElement.style.cursor = 'grabbing'
}, 100) // 每100毫秒检查一次状态, 鼠标移出要主动清理
}, 100) // 0.1秒延迟抓取
@ -100,30 +102,25 @@ export default class DragControl implements IControls {
if (!isNaN(this.dragStartMouse.x) && !isNaN(this.dragStartMouse.y) && this.dragShadowsGroup) {
this.isDragging = true
this.domElement.style.cursor = 'grabbing'
// 更新阴影位置(锁定 Y 轴)
this.updateShadows(new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z))
} else {
const mouse = this.getMousePosition(event.clientX, event.clientY)
const intersected = this.getIntersectedDraggableObject(mouse)
if (intersected) {
this.domElement.style.cursor = 'grab'
} else {
this.domElement.style.cursor = 'auto'
}
this.domElement.style.cursor = intersected ? 'grab' : 'auto'
}
}
/**
* pointerup
*/
private onPointerUp = (event: PointerEvent): void => {
if (this.isDragging) {
const startPos = this.dragStartMouse
const startPos = this.dragStartMouse.clone()
const targetPos = new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z)
if (startPos && targetPos) {
if (startPos && targetPos && !_.isNaN(startPos.x) && !_.isNaN(startPos.y)) {
this.dragComplete(startPos, targetPos)
}
}
@ -139,16 +136,16 @@ export default class DragControl implements IControls {
this.domElement.style.cursor = 'auto'
}
if (this.viewport) {
this.viewport.controls.enabled = true
}
this.isDragging = false
this.isPointerDown = false
this.dragStartMouse.set(NaN, NaN)
this.removeShadows()
if (this.viewport) {
this.viewport.controls.enabled = true
}
if (this.dragDelayTimeout !== null) {
clearTimeout(this.dragDelayTimeout)
this.dragDelayTimeout = null
@ -186,13 +183,6 @@ export default class DragControl implements IControls {
}
}
private static readonly SHADOW_MATERIAL = new THREE.MeshBasicMaterial({
color: 0x222222,
transparent: true,
opacity: 0.5,
depthWrite: false,
side: THREE.DoubleSide
})
/**
*
@ -200,15 +190,11 @@ export default class DragControl implements IControls {
private createShadows(objects: THREE.Object3D[]): void {
this.removeShadows()
console.log('createShadows', objects.map(obj => obj.name))
this.dragShadowsGroup = new THREE.Group()
// 初始位置为 (0, 0, 0)
this.dragShadowsGroup.position.set(0, 0, 0)
for (const obj of objects) {
if (!obj.userData.entityId) {
console.error('Object does not have entityId:', obj.name)
continue // 跳过没有 entityId 的对象
if (_.isNil(_.get(obj, 'userData.entityId'))) {
console.error(`Object ${obj.name} missing entityId`)
continue
}
// 克隆对象的几何体和材质

Loading…
Cancel
Save