适用场景:安装了「FineVis数据可视化」插件的用户,可参考本文了解 FineVis 的相关功能。
版本
| 报表服务器版本 | 插件版本 | 功能变动 | 
|---|---|---|
| 11.0.16 | V1.15.0 | 新增控制模型轨迹运动接口:rotateTo 、rotateForwardTo 、scaleTo 、moveTo  | 
接口说明
以下接口支持 三维自定义场景组件 以及 三维城市场景组件 中的自定义模型,获取模型对象后,可通过接口设置模型沿特定轨迹运动、转向、缩放等效果。
| 方法 | 含义 | 参数说明 | 
|---|---|---|
| rotateTo() | 模型从当前欧拉角转到指定欧拉角 注:欧拉角表示模型在 x-y-z 三个轴上的旋转角度  | rotation:模型欧拉角,例如 [0,90,0] option:模型转向动画时长、回调监听  | 
rotateForwardTo()  | 模型从当前朝向转到指定朝向 | forward:指定朝向的方向向量,例如 [0, 1, 0] coord:{rotation,forward} 描述模型坐标系的正面方向 option:模型转向动画时长、回调监听  | 
scaleTo()  | 模型从当前大小缩放到另一个大小 | scale:模型大小 option:模型缩放动画时长、回调监听  | 
moveTo()  | 模型从当前位置移动到下一个位置 | position:模型位置 coord:{rotation,forward}|boolean 描述模型坐标系的正面方向 option:模型移动动画时长、回调监听 rotateForwardOption:模型朝向旋转参数  | 
接口 option 说明
动画时长相关规则
duration 和 speed 属性,都可以指定动画时长,但二者应用场景不同,一般只需要给出一个属性即可;若两者都存在,优先使用 duration。
1)duration:用于直接指定动画时长,单位 秒,需大于等于 0;当 duration = 0 时,表示无动画效果,立即变换到指定状态。
2)speed:通过设置动画速度来指定动画时长,单位 1/秒,需大于 0 。比如给定 speed 的情况下,moveTo 到更远的位置,需要的时间更多。
回调监听相关规则
1)onTransforming: (factor, value) => { func(); } 用于监听动画执行过程中的模型属性的变化,以及动画进度。
factor 表示动画进度,范围为[0, 1] 。动画开始时 factor 为0,动画结束时,factor 为 1。
value 表示动画属性,对于 moveTo ,value 为模型位置,rotateTo 或 rotateForwardTo,value 为模型旋转角度。
2)onTransformCompleted: () => { func(); } 动画结束时调用函数。
使用限制
模型的缩放(scaling)需为 [1, 1, 1] 的比例,本文接口才能实现正确效果,例如 [2, 2, 2] 或 [-1, -1, -1] 。
若是 [1,1,-1] 或 [1,1,2] 这样的比例,接口仍可使用,但对应效果不正确。
如下图所示:

接口示例
rotateTo
实现方式如下:
export type IMeshAnimationInfo<T> = {
  onTransforming?: (factor: number, value: T) => void;
  onTransformCompleted?: () => void;
  duration?: number;
  speed?: number;
};
 
rotateTo(
    rotation: NumberArray3,
    option: IMeshAnimationInfo<NumberArray3>
  ): void;
实现案例如下:
//场景一:同时传合法的duration和speed,duration生效
setTimeout(function(){
    const widget=duchamp.getWidgetByName("3D");
    const taxi=widget.getMeshByName("taxi");
    
    //目标欧拉角
    const nextRotation = [100, 190, -60];
    
    //渐变过程
    rotationOption={ 
        //同时传合法的duration和speed,duration生效
        duration:5,//模型转向时间,单位s
        speed:50,//模型转向角速率
        //回调监听:模型转向中
        onTransforming:(factor,value)=>{
            if(factor==0){//动画开始
                console.log("动画开始:模型渐变(duration=5s)到目标欧拉角")
                console.log("taxi的rotation:"+taxi.rotation)
            }
        },
        ////回调监听:模型转向结束
        onTransformCompleted: () => {
            console.log("模型转向结束:顺时针旋转,rotation:  [100, 180, -60] === ["+taxi.rotation+" ]")
        }
    }
    
    //执行模型从当前欧拉角转到指定欧拉角
    taxi.rotateTo(nextRotation, rotationOption);
    },1000)
效果如下图所示:

rotateForwardTo
实现方法如下:
type MeshForward = {
  rotation?: NumberArray3;
  direction?: NumberArray3;
};
 
const DefaultMeshForward: MeshForward = {
  rotation: [0, 0, 0],
  direction: [0, 0, 1],
};
 
export type IMeshAnimationInfo<T> = {
  onTransforming?: (factor: number, value: T) => void;
  onTransformCompleted?: () => void;
  duration?: number;
  speed?: number;
};
 
rotateForwardTo(
    direction: NumberArray3,
    option: IMeshAnimationInfo<NumberArray3> & { forward?: MeshForward }
  ): void;
实现案例如下:
 //场景二:指定朝向: rotation & forward
     setTimeout(function(){
        const widget=duchamp.getWidgetByName("3D");
        const taxi=widget.getMeshByName("taxi");
        //期望的模型朝向的方向向量
        const nextForwardDirection = [1, 1, 1];
        //模型坐标架的正面朝向:当前场景,车顶为模型的正面朝向
        const coord={
            rotation:[0,0,0],
            forward:[0,1,0]
        }
        //渐变过程
        rotateForwardOption1={
            duration: 4, 
            speed:60,
            coord,
            onTransforming:(factor,value)=>{
                if(factor==0){
                    console.log("动画开始>>>>>定义朝向")
                    console.log("taxi的scaling:"+taxi.scaling)
                    taxi.setScaling([15,15,15])  
                }
            },
            onTransformCompleted: () => {
                console.log("模型转向结束:顺时针旋转,车顶朝向为坐标轴的[1, 1, 1]方向")
                console.log("taxi的scaling:"+taxi.scaling)
            }
        }
        //模型渐变至指定朝向
        taxi.rotateForwardTo(nextForwardDirection, rotateForwardOption1);
    
        },1000)
效果如下图所示:

scaleTo
实现方法如下:
export type IMeshAnimationInfo<T> = {
  onTransforming?: (factor: number, value: T) => void;
  onTransformCompleted?: () => void;
  duration?: number;
  speed?: number;
};
 
scaleTo(
    scaling: NumberArray3,
    option: IMeshAnimationInfo<NumberArray3>
  ): void;
实现案例如下:
//场景三:变换缩放大小
setTimeout(function(){
    const widget=duchamp.getWidgetByName("3D");
    const taxi=widget.getMeshByName("taxi");
    //目标缩放值
    const nextScale = [5, 5, 5];
    //缩放过程
    scaleOption={
        duration: 3, 
        onTransforming:(factor,value)=>{
            if(factor==0){
                console.log("taxi的scale:"+taxi.scaling)
                console.log("动画开始")
            }
        },
        onTransformCompleted: () => {
            console.log("模型缩放结束:taxi的scale:[5, 5, 5]==="+taxi.scaling)
        }
    }
    //模型从当前大小缩放到目标大小
    taxi.scaleTo(nextScale, scaleOption);
    },1000)
效果如下图所示:

moveTo
实现方法如下:
type MeshCoord = {
  rotation?: NumberArray3;
  forward?: NumberArray3;
};
  
const DefaultMeshCoord: MeshCoord = {
  rotation: [0, 0, 0],
  forward: [0, 0, 1],
};
 
export type IMeshAnimationInfo<T> = {
  onTransforming?: (factor: number, value: T) => void;
  onTransformCompleted?: () => void;
  duration?: number;
  speed?: number;
};
 
export type IMeshForwardRotationInfo<T> = IMeshAnimationInfo<T> & { coord?: MeshCoord }
 
moveTo(
    position: NumberArray3,
    option: IMeshAnimationInfo<NumberArray3>,
    rotateForwardOption?: IMeshForwardRotationInfo<NumberArray3>
  ): void;
实现案例如下:
//场景四:先转向后移动
 setTimeout(function(){
    const widget=duchamp.getWidgetByName("3D");
    const taxi=widget.getMeshByName("taxi");
     //目标位置
    const nextPosition = [-6, 37, -8];
    
    // 模型旋转时长: 模型坐标架的正面朝向
    const coord = { rotation: [0, -90, 0], forward: [1, 0, 0]};
    
    //模型转向过程 :正面朝向转动,指向目标位置
    const rotateForwardOption = {
        coord, 
        duration: 3,
        onTransforming:(factor,value)=>{
        if(factor==0){
            console.log("taxi的rotation:"+taxi.rotation)
            console.log("转向开始,顺时针旋转")
        }
    },};
    // 模型沿直线运动到下一位置, 并自动旋转模型朝向沿轨迹方向
    positionOption={ 
        duration: 3, 
        onTransforming:(factor,value)=>{
            if(factor==0){
                console.log("taxi的position:"+taxi.position)
                console.log("开始移动") 
            }
        },
    
        onTransformCompleted: () => {
            console.log("模型结束转向&移动:position的scale:[-6, 37, -8]==="+taxi.position)
        }
    }
     //模型从当前位置移动到下一个位置:先转向(把正面朝向指向目标位置转向),再沿直线运动到目标位置
    taxi.moveTo(nextPosition, positionOption,rotateForwardOption);
    },1000)
效果如下图所示:

注:moveTo 可以不规定转向,直接规定 nextPosition 即可实现垂直或水平方向的移动。下面给出两个示例,主要是实现方式的差别,选择合适的使用即可。
示例1:
 setTimeout(function(){
    const widget=duchamp.getWidgetByName("3D");
    const taxi=widget.getMeshByName("taxi");
     //目标位置
    const nextPosition1 = [taxi.position[0],taxi.position[1]+5, taxi.position[2]];
    const nextPosition2 = [taxi.position[0]-10,taxi.position[1]+5, taxi.position[2]];
    // 模型运动时长
    positionOption={ 
        duration: 3, 
        onTransforming:(factor,value)=>{
            if(factor==0){
                console.log("taxi的position:"+taxi.position)
                console.log("开始移动") 
            }
        },
    
        onTransformCompleted: () => {} }
     //模型从当前位置移动到下一个位置
    taxi.moveTo(nextPosition1, positionOption,'');
 setTimeout(function(){
    taxi.moveTo(nextPosition2, positionOption,'');
    },4000)
    },1000)
示例2:
setTimeout(function () {
    const widget = duchamp.getWidgetByName("3D");
    const taxi = widget.getMeshByName("taxi");
    //目标位置
    const nextPosition1 = [
      taxi.position[0] + 69,
      taxi.position[1],
      taxi.position[2],
    ];
    const nextPosition2 = [
      taxi.position[0] + 69,
      taxi.position[1],
      taxi.position[2] - 183,
    ];
    const positions = [
      nextPosition1,
      nextPosition2
    ];
    // 模型运动时长
    const positionOption = {
      duration: 10,
      onTransforming: (factor, value) => {
        if (factor == 0) {
          console.log("taxi的position:" + taxi.position);
          console.log("开始移动");
        }
      },
    };
    function moveToNextPosition() {
      const nextPosition = positions.shift();
      taxi.moveTo(
        nextPosition,
        Object.assign({}, positionOption, {
          onTransformCompleted: () => {
            moveToNextPosition();
          },
        }),
        "",
      );
    }
    moveToNextPosition();
  }, 1000);
 模板下载
点击下载模板:模型轨迹运动JS示例.fvs
