给 Three.js 里面的 OrbitControls 控制器添加上 缩放阻尼 效果

534 阅读1分钟

直接在源码上动手, 注释的地方是追加的

源码位于 three/examples/jsm/controls/OrbitControls.js

1.在这个位置里加上 参数 this.zoomDistance = 0; this.zoom_copy_radius = 0

// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
// Set to false to disable zooming
    this.enableZoom = true;
    this.zoomSpeed = 1.0;
    this.zoomDistance = 0;       // 加上这个参数,代表缩放的距离大小
    this.zoom_copy_radius = 0;   // 加上这个参数,复制一份当前缩放大小
    
// Set to false to disable rotating
    this.enableRotate = true;
    this.rotateSpeed = 1.0;

2.在这个俩个函数里加上 额外追加的, 有注释的即使

    function dollyOut(dollyScale) {

      if (scope.object.isPerspectiveCamera) {
        
        scope.zoom_copy_radius ||= spherical.radius  // 复制一份
        scale /= dollyScale;
        scope.zoomDistance -= (scope.zoom_copy_radius - scope.zoom_copy_radius * scale); // 累加距离
        scope.zoom_copy_radius *= scale;  // 重新赋值复制出来的
        
      } else if (scope.object.isOrthographicCamera) {

        scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
        scope.object.updateProjectionMatrix();
        zoomChanged = true;

      } else {

        console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
        scope.enableZoom = false;

      }

    }

    function dollyIn(dollyScale) {

      if (scope.object.isPerspectiveCamera) {

        scope.zoom_copy_radius ||= spherical.radius  // 复制一份
        scale *= dollyScale;
        scope.zoomDistance -= (scope.zoom_copy_radius - scope.zoom_copy_radius * scale); // 累加距离
        scope.zoom_copy_radius *= scale;   // 重新赋值复制出来的

      } else if (scope.object.isOrthographicCamera) {

        scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
        scope.object.updateProjectionMatrix();
        zoomChanged = true;

      } else {

        console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
        scope.enableZoom = false;

      }

    }

3.最后在 update 函数里面, 把 spherical.radius *= scale 改掉

this.update = function () {
    //------

        // spherical.radius *= scale  // 这里注释掉
        if (scope.enableDamping === true) {  // 追加上这个判断
        
          spherical.radius += scope.zoomDistance * scope.dampingFactor
          scope.zoomDistance *= (1 - scope.dampingFactor)

        } else {

          spherical.radius *= scale

        }
        
        if (spherical.radius < scope.minDistance || spherical.radius > scope.maxDistance) {  // 再追加上这个,超过边距就重置为 0
          scope.zoomDistance = 0
        }
        
        // restrict radius to be between desired limits
        spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
        scope.zoom_copy_radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.zoom_copy_radius)); // 追加
        
        
   //-------
}();