Skip to content

135. 实战:实现酷家乐同款拖拽旋转控制器(五)

Published:

上节把旋转箭头画出来了:

2025-09-20 11.53.12.gif

这节加上拖拽旋转的交互。

拖拽改变位置只要知道拖动到的点就行,用它来设置位置。

这里我们可以判断鼠标在水平方向的拖动距离来改变旋转角度:

我们来写一下:

image.png

声明两个变量记录开始的鼠标位置和旋转角度,并且加一个 rotating 状态。

let initialMousePosition = new THREE.Vector2();
let initialRotation = 0;
let rotating = false;
const intersections = rayCaster.intersectObjects([
    arrowFrontMesh,
    arrowLeftMesh,
    arrowTopMesh,
    arrowRotateMesh
]);

在 mousedown 的时候记录下数据:

image.png

case 'arrowRotate':
rotating = true;
initialMousePosition.set(x, y);
initialRotation = this.obj.rotation.y;
break;

记录当前鼠标位置和旋转角度。

然后 mousemove 的时候,根据 x 轴方向移动的距离来改变 rotation.y

image.png

mouseup 的时候重置下。

if(rotating) {
    controls.enabled = false;

    const deltaX = x - initialMousePosition.x;

    const s = 5.0;
    const rotationAngle = deltaX * s;

    this.obj.rotation.y = initialRotation + rotationAngle;
}
rotating = false;

这里就是判断鼠标在水平方向移动了多少距离,用它乘以一个系数来改变旋转角度。

试下效果:

2025-09-20 17.51.50.gif

这样,拖拽旋转功能就完成了。

我们换一个模型试试:

https://github.com/mrdoob/three.js/blob/e9144842962d46f0ab4a7049cc072ad201d9659d/examples/models/gltf/Michelle.glb

image.png

下载下来放到 public 目录下:

image.png

替换下:

image.png

看下效果:

2025-09-20 17.57.07.gif

位移和旋转都没问题。

然后加一下改变一个方向的位置或者角度的时候,其余箭头隐藏的效果:

2025-09-20 18.02.17.gif

mousemove 的时候,把其他三个箭头隐藏:

image.png

arrowFrontMesh.visible = false;
arrowTopMesh.visible = false;
arrowRotateMesh.visible = false;

mouseup 的时候恢复:

image.png

arrowLeftMesh.visible = true;
arrowFrontMesh.visible = true;
arrowTopMesh.visible = true;
arrowRotateMesh.visible = true;

试一下:

2025-09-20 18.06.25.gif

这个方向的效果没问题。

然后把其余三个箭头的也加一下:

image.png

image.png

if(draggingY) {
    arrowLeftMesh.visible = false;
    arrowFrontMesh.visible = false;
    arrowRotateMesh.visible = false;
if(draggingZ) {
    arrowLeftMesh.visible = false;
    arrowTopMesh.visible = false;
    arrowRotateMesh.visible = false;
if(rotating) {
    arrowLeftMesh.visible = false;
    arrowFrontMesh.visible = false;
    arrowTopMesh.visible = false;

2025-09-20 18.09.27.gif

这样,我们自己实现的仿酷家乐控制器就完成了。

当然,很多细节不一样,这些可以自己完善,核心还是交互逻辑。

案例代码上传了小册仓库

总结

这节我们实现了拖拽旋转的功能。

mousedown 的时候,如果是选中了黄色箭头,就加一个 rotating 状态。

记录最开始的位置和旋转角度。

mousemove 的时候,根据鼠标在水平方向移动的距离来改变 rotation.y 角度

这样就实现了拖拽旋转的功能。

然后我们又优化了一下细节,选中一个箭头的时候,其余箭头隐藏。

这样,我们的仿酷家乐控制器就完成了。

如果你觉得内置的 TransformControls 不好用的时候,也可以根据自己的需求来写一个。

评论