Threejs基于TransfromControls控制器实现单方向缩放

Threejs基于TransfromControls控制器实现单方向缩放

一、前言

我们遇到了这样的问题,创建一个长方体,当鼠标选中X轴正方向拉伸时,其负方向的部分要不拉伸,视觉效果为固定一面不动。官方自带的TransfromControls,是同时缩放X、Y、Z缩放轴的正负轴,拉伸一边另外一边也随之而动。不满足我们的需要,需要通过特殊的方式去处理。

二、正确的思路

  1. 缩放还是要缩放的,只是缩放的同时要控制物体沿着缩放的方向进行正确的移动,看上去就实现了固定一边
  2. 实现的效果在多边缩放时无法预知移动的方向,所以只有沿着 X Y Z的某方向缩放才能实现,XY XZ YZ这样的缩放仍然是沿用官方插件的实现

三、代码实现

1.不改动TransfromControls源码的方式

  1. 监听渲染场景的鼠标click事件,选中对象时计算出,相对中心点的拖拽方向向量,后面计算的时候用
  _self.renderer.domElement.addEventListener('click', function (event) {
                event.preventDefault();
                if (!_self.elem) return;
                let mouse = new THREE.Vector2();
                let raycaster = new THREE.Raycaster();
                let top = _self.offsetTop(_self.elem);
                let left = _self.offsetLeft(_self.elem);
                mouse.x = ((event.clientX - left) / _self.elem.clientWidth) * 2 - 1;
                mouse.y = -((event.clientY - top) / _self.elem.clientHeight) * 2 + 1;
                raycaster.setFromCamera(mouse, _self.camera);
                let intersects = raycaster.intersectObjects(_self.scene.children);
                if (intersects.length > 0) {
                    let object = intersects[0].object;
                    if (object.userData.type == null) return false;
                    //就在点击的时候就存下相对位置
                    _self.point = intersects[0].point.clone().sub(object.position);
                    _self.point.x = Math.sign(_self.point.x);
                    _self.point.y = Math.sign(_self.point.y);
                    _self.point.z = Math.sign(_self.point.z);
                    _self.transformControl.attach(object)
                    _self.prevScale.copy(object.scale);
                }
            });
  1. 监听TransfromControls的objectChange,缩放的同时计算要移动的距离
_self.transformControl.addEventListener('objectChange', function () {
                let object = _self.transformControl.object;
                let curScale = object.scale.clone();
                let direction = curScale.clone().sub(_self.prevScale);
                //只有缩放模式起作用 而且只对单一缩放起作用
                if(_self.transformControl.getMode() === 'scale'){
                    object.geometry.computeBoundingBox();
                    let distance = object.geometry.boundingBox.getSize(new THREE.Vector3()).multiplyScalar(0.5).multiply(direction).multiply(_self.point);
                    //得到了移动方向 判断移动的是哪个轴
                    //通过鼠标点位置相对于 矩形中心点位置来判断是负方向还是正方向 相对位置是正则正 负则负
                    //一起判断移动的相对正负 仅仅对轴的缩放起作用
                    if(direction.x != 0 && direction.y == 0 && direction.z == 0
                        || direction.x == 0 && direction.y != 0 && direction.z == 0
                        || direction.x == 0 && direction.y == 0 && direction.z != 0){
                            object.position.add(distance);
                        }
                }
                // 更新上一个缩放值
                _self.prevScale.copy(curScale); 
            });

2.改动TransfromControls

  1. 思路魔改的TransfromControls,在它的object中存储拖拽的方向
    下载地址 https://files.cnblogs.com/files/lovefoolself/TransformControls.js?t=1706152892&download=true
  2. 代码实现
    image
posted @ 2024-01-25 11:36  lovefoolself  阅读(468)  评论(0)    收藏  举报