
源码
  flyTo(object, gltfthis) {
    if (object === undefined || object === null) {
      return;
    }
    const box3 = new THREE.Box3();
    box3.expandByObject(object); // 计算模型包围盒
    const size = new THREE.Vector3();
    box3.getSize(size); // 计算包围盒尺寸
    const center = new THREE.Vector3();
    box3.getCenter(center); // 计算一个层级模型对应包围盒的几何体中心坐标
    function maxSize(vec3) {
      let max;
      if (vec3.x > vec3.y) {
        max = vec3.x;
      } else {
        max = vec3.y;
      }
      if (max < vec3.z) {
        max = vec3.z;
      }
      return max;
    }
    const max = maxSize(size); // 包围盒长宽高中最大的一个值,用来表征模型的尺寸
    var tmp = center.clone().addScalar(max);
    var newPos = new THREE.Vector3(tmp.x, tmp.y, tmp.z);
    newPos.y = newPos.y + 3.0;
    newPos.z = newPos.z + 2.0;
    var targetPos = new THREE.Vector3(center.x, center.y, center.z);
    targetPos.y = targetPos.y + 1;
    let tis = this;
    if (object.type == "Group") {
      tis = gltfthis;
    }
    tis.animateCameraFun(
      tis.camera.position,
      tis.controls.target,
      newPos,
      targetPos,
      2000
    );
  },-  参数检查与初始化: - 首先检查传入的 object是否为undefined或null,如果是则直接返回,不执行后续的操作。
 
- 首先检查传入的 
-  计算包围盒和尺寸: - 使用 THREE.Box3来计算传入对象object的包围盒 (box3)。
- 通过 box3.getSize(size)获取包围盒的尺寸size。
- 使用 box3.getCenter(center)获取包围盒的中心坐标center。
 
- 使用 
-  计算模型尺寸的最大值: - 定义了一个函数 maxSize(vec3),用来返回三维向量vec3中的最大值,即包围盒尺寸的长、宽、高中的最大值。
 
- 定义了一个函数 
-  计算新的相机位置 ( newPos) 和目标位置 (targetPos):- 计算出最大尺寸 max,然后基于包围盒的中心center和最大尺寸max计算出新的相机位置newPos,稍微偏移了一定的距离(y轴上+3.0,z轴上+2.0)。
- 计算目标位置 targetPos,也稍作偏移(y轴上+1)。
 
- 计算出最大尺寸 
-  动态设置 tis对象:- 根据传入的 object的类型,动态选择tis对象。如果object.type是"Group",则将tis设置为gltfthis,否则保持原先的this。
- 如果是创建mesh不需要这部,因为我gitf模型的处理是用回调去处理添加的gltb模型。so需要手动传入this。
 
- 根据传入的 
-  调用相机动画函数: - 最后调用 tis.animateCameraFun()方法,传入相机位置 (tis.camera.position)、控制器的目标位置 (tis.controls.target)、新的相机位置 (newPos)、目标位置 (targetPos),以及动画持续的时间(2000毫秒)。
 
- 最后调用 
动画源码
  /**
   *
   * @param {*} oldPos 原来相机位置
   * @param {*} oldTarget  原来controls
   * @param {*} newPos new相机位置
   * @param {*} newTarget   new controls
   * @param {*} time
   */
  animateCameraFun(oldPos, oldTarget, newPos, newTarget, time) {
    const that = this;
    if (time === undefined || time === null) {
      time = 1000;
    }
    // 使用tween动画
    var tween = new TWEEN.Tween({
      x1: oldPos.x, // 相机x
      y1: oldPos.y, // 相机y
      z1: oldPos.z, // 相机z
      x2: oldTarget.x, // 控制点的中心点x
      y2: oldTarget.y, // 控制点的中心点y
      z2: oldTarget.z, // 控制点的中心点z
    });
    tween.to(
      {
        x1: newPos.x,
        y1: newPos.y,
        z1: newPos.z,
        x2: newTarget.x,
        y2: newTarget.y,
        z2: newTarget.z,
      },
      time
    );
    tween.easing(TWEEN.Easing.Cubic.InOut);
    tween.onUpdate(function (pos) {
      // that.renderScene2();
      that.camera.position.x = pos.x1;
      that.camera.position.y = pos.y1;
      that.camera.position.z = pos.z1;
      that.controls.target.x = pos.x2;
      that.controls.target.y = pos.y2;
      that.controls.target.z = pos.z2;
      that.camera.updateProjectionMatrix(); // 渲染范围改变,注意更新投影矩阵
      that.controls.update();
    });
    tween.onComplete(function () {
      that.controls.update();
    });
    // 开始动画
    tween.start();
  }, 函数定义:animateCameraFun 是一个函数,接受旧的相机位置 (oldPos) 和目标点 (oldTarget),以及新的相机位置 (newPos) 和目标点 (newTarget),还有一个可选的动画时间参数 (time)。
Tween 动画设置:使用 tween.js 库创建动画效果,实现平滑过渡。
这里创建了一个 Tween 对象,定义了初始状态(旧的相机位置和目标点)和最终状态(新的相机位置和目标点),以及动画的时间参数。
Tween 设置目标:通过 tween.to() 方法设置 Tween 的目标状态和动画时间。
缓动函数:使用 tween.easing() 方法设置缓动函数,这里使用了 TWEEN.Easing.Cubic.InOut,表示缓入缓出的三次方缓动效果。
Tween 更新和完成时的操作:
- tween.onUpdate()方法在 Tween 更新时执行,更新相机和控制器的位置和目标点,并更新投影矩阵。
- tween.onComplete()方法在 Tween 完成时执行,确保最后一次更新控制器的状态。
启动动画:最后调用 tween.start() 开始动画效果。 
关键的地方:在render循环里面记得加 TWEEN.update();

 
???????????????????




















