Browse Source

EsDragControl 延迟抓取

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

80
src/core/controls/DragControl.ts

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

Loading…
Cancel
Save