我正在尝试在三个 js 渲染上创建一个边界框缩放,用户可以在其中拖动一个框,然后相机将缩放有界区域。但是,该框未正确生成。 ` 公共 DragZoom(值: 布尔值): void { const 几何 = new THREE.PlaneGeometry(1, 1); const 材质 = new THREE.MeshBasicMaterial({ 颜色:0x808080, 不透明度:0.1, 透明:真实, });
let mesh = new THREE.Mesh(geometry, material);
let isDragging = false;
let initialCursorPos = new THREE.Vector2();
let initialBoxPos = new THREE.Vector3();
const borderGeometry = new THREE.EdgesGeometry(geometry);
const borderMaterial = new THREE.LineBasicMaterial({ color: 0x000000, linewidth: 2 });
const borderLines = new THREE.LineSegments(borderGeometry, borderMaterial);
mesh.add(borderLines);
const onMouseDown = (event: MouseEvent) => {
isDragging = true;
initialCursorPos.x = event.clientX;
initialCursorPos.y = event.clientY;
initialBoxPos.x = (event.clientX / window.innerWidth) * 2 - 1;
initialBoxPos.y = -(event.clientY / window.innerHeight) * 2 + 1;
mesh.position.set(initialBoxPos.x, initialBoxPos.y, 0);
this.scene.add(mesh);
};
const onMouseMove = (event: MouseEvent) => {
if (isDragging) {
const deltaX = (event.clientX - initialCursorPos.x) / 40; // Divide by a smaller value for less aggressive scaling
const deltaY = (event.clientY - initialCursorPos.y) / 40; // Divide by a smaller value for less aggressive scaling
mesh.scale.set(deltaX, deltaY, 1);
const boxSize = new THREE.Box3().setFromObject(mesh).getSize(new THREE.Vector3());
const width = boxSize.x;
const height = boxSize.y;
const newX = initialBoxPos.x + (width / 2) * Math.sign(deltaX);
const newY = initialBoxPos.y - (height / 2) * Math.sign(deltaY);
mesh.position.set(newX, newY, 0);
}
};
const onMouseUp = () => {
if (isDragging) {
isDragging = false;
const boundingBox = new THREE.Box3().setFromObject(mesh);
const boxSize = boundingBox.getSize(new THREE.Vector3());
const cameraAspect = this.camera.aspect;
const horizontalPadding = (boxSize.x - boxSize.y * cameraAspect) / 2;
const verticalPadding = (boxSize.y - boxSize.x / cameraAspect) / 2;
this.controls.fitToBox(mesh, true, {
paddingTop: verticalPadding,
paddingBottom: verticalPadding,
paddingLeft: horizontalPadding,
paddingRight: horizontalPadding,
});
this.scene.remove(mesh);
mesh = null;
}
};
this.renderer.domElement.addEventListener('mousedown', onMouseDown);
this.renderer.domElement.addEventListener('mousemove', onMouseMove);
this.renderer.domElement.addEventListener('mouseup', onMouseUp);
}`
我尝试使用mesh.position,但它似乎没有影响任何东西。
大多数情况下,屏幕坐标不能直接用作场景内实体的坐标。
mesh.position.set(initialBoxPos.x, initialBoxPos.y, 0);
您需要检查您的相机;场景中的 1 个长度单位很可能与屏幕上的 1 个像素不同。
您需要将屏幕坐标转换为场景坐标,这取决于相机,如下所示:
const canvasBounds = canvas.getBoundingClientRect();
const ndc = {
x: ((clientX - canvasBounds.left) / canvas.width) * 2 - 1,
y: (-(clientY - canvasBounds.top) / canvas.height) * 2 + 1,
z: 0,
};
const worldPosition = new THREE.Vector3(ndc.x, ndc.y, ndc.z);
worldPosition.unproject(camera);
NDC的含义是标准化设备坐标。 NDC 空间中的所有坐标范围为 [−1, 1]