最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 基于路径集合的三维动画链

    正文概述 掘金(ITMan彪叔)   2020-11-26   370

    目前数据信息可视化的发展趋势越来越快,纬度宽广、数量庞大、结构复杂的数据展示仅仅只依靠二维平面图表已经不能满足了。为了更加清晰,快速的认知和理解一份数据,构建基于现实的三维虚拟可视化效果,被广泛应用到各行业中,迅速成为信息数字化管理的重要组成部分。   三维场景还原了现实的虚拟效果,而各种各样的动画则赋予其更加饱满、灵动的视觉冲击。基于路径集合的三维动画链,它充实了场景中元素的动画效果,接下来我会具体介绍动画链的实现过程。

    基于路径集合的三维动画链

    1、配置路径数据

    此次示例中模型均采用gltf格式,以上图场景中小车为例,在模型加载完成后,我们定义配置好一系列的路径点(animatePath),让小车按照该路径执行动画。

    scene.loadGLTF('./static/gltf/car1/1.gltf', {
      generateTangent: true,
      useIBLWhenMissingTexture: true,
      loadTexture: true,
    }).then((data) => {
      const element = data.root;
      element.scale = [0.1, 0.1, 0.1];
      element.ry = Math.PI;
      element.position = [98, 1.5, -125];
      
      const { y } = element;
      const animatePath = [
        [98, y, -135],
        [50, y, -135],
        [10, y, -95],
        [-30, y, -125]
      ]
      
      // 创建动画链
      element.animate = this.createPathAnimates(element, animatePath, () => {
        // 动画链结束后的处理
        ... ...
      });
      
      element.animate.play();
    })
    
    

    其中animatePath的配置,为了满足不同的场景需求,我们可以通过各种方式去实现它的定义; 例如:

    • 在场景中通过可视化的打点操作形成路径
    • 在该场景元素的属性面板中,进行JSON数据的配置
    • 对于精准规范的路径,可以通过接口返回的数据处理
    • ... ...

    2、创建动画链

    实现小车路径集合的动画链,在遍历路径的时候,需要注意两个过程,一个是小车的moveAnimate(小车沿路径移动的动画),另一个则是每一次moveAniamte之前的rotationAniamte(小车在下一段路径动画前的朝向动画);

    createPathAnimates(element, points, done) {
      // 声明一个有序的动画集合,方便后面进行动画链处理
      const animates = [];
      if (points && points.length > 0) {
        // 获取小车的初始位置和旋转角度
        let { x, y, z } = element;
        let angle = element.ry;
        for (let i = 0, len = points.length; i < len; i++) {
          const point = points[i];
          const x1 = point[0];
          const z1 = point[2];
          // 计算下一段与上一段之间的角度,创建rotateAnimate 
          const rotate = Math.atan2(-(z1 - z), x1 - x);
          const rotateAnimate = this.createRotateAnimate(element, rotate, angle);
          if (rotateAnimate) {
            animates.push(rotateAnimate);
            angle = rotateAnimate.toAngle;
          }
          // 创建moveAnimate 
          const moveAnimate = this.createMoveAnimate(element, [x, z], [x1, z1]);
          if (moveAnimate) {
            animates.push(moveAnimate);
            x = x1;
            z = z1;
          }
        }
      }
    
      // done为动画链接结束后的回调处理函数
      animates[animates.length - 1].onDone = done;
      let animate;
      for (let i = 0, len = animates.length; i < len; i++) {
        if (i > 0) {
          animates[i - 1].chain(animates[i]);
        } else {
          animate = animates[i];
        }
      }
    
      return animate;
    }
    
    

    2.1、rotationAniamte

    通过Math.atan2()方法,获取相对的偏移弧度:

    基于路径集合的三维动画链 与小车的当前弧度进行比较创建rotationAnimate:

    createRotateAnimate(element, toAngle, angle) {
      if (toAngle !== angle) {
        if (toAngle - angle > Math.PI) {
          toAngle -= Math.PI * 2;
        }
        if (toAngle - angle < -Math.PI) {
          toAngle += Math.PI * 2;
        }
      }
      const rotateAnimate = new Animate({
        from: angle,
        to: toAngle,
        type: 'number',
        dur: Math.abs(toAngle - angle) * 300,
        easing: 'easeNone',
        onPlay() {
          element.animate = this;
        },
        onUpdate(value) {
          element.ry = value + (Math.PI / 2);
        },
      });
      rotateAnimate.toAngle = toAngle;
      return rotateAnimate;
    }
    

    2.2、moveAnimate

    通过上一段与下一段的point创建moveAniamte:

    createMoveAnimate(element, [x, z], [x1, z1]) {
      return new Animate({
        from: [x, z],
        to: [x1, z1],
        type: 'point',
        dur: Math.sqrt((x1 - x) ** 2 + (z1 - z) ** 2) * 100 || 100,
        easing: 'easeNone',
        onUpdate(value) {
          const [x, z] = value;
          element.position = vec3.fromValues(x, element.y, z);
        },
      });
    }
    

    2.3、动画链式衔接

    处理好对应的rotationAniamte和moveAnimate后,采用动画实例对象的chain方法进行链式衔接,最终的动画实力对象就能够实现我们的动画效果了,同时可以处理动画链结束后的其他操作:

    createPathAnimates(element, points, done) {
      // 声明一个有序的动画集合,方便后面进行动画链处理
      const animates = [];
      ... ...
      // done为动画链接结束后的回调处理函数
      animates[animates.length - 1].onDone = done;
      let animate;
      for (let i = 0, len = animates.length; i < len; i++) {
        if (i > 0) {
          animates[i - 1].chain(animates[i]);
        } else {
          animate = animates[i];
        }
      }
    
      return animate;
    }
    
    

    3、动画链效果

    以上述示例来说,最终小车的动画效果:

    基于路径集合的三维动画链

    至此,一个基于路径集合的动画链就完成了,实现的原理也并不复杂;有了这样的动画链机制,我们就可以实现以路径为核心的不同的动画效果,广泛应用到各种动画需求的场景当中。

    例如,仓库中的作业流程: 基于路径集合的三维动画链 除了把路径动画链应用到场景元素上,我们还可以应用到三维场景的镜头上面,这样一来就能够实现巡航的动画效果: 基于路径集合的三维动画链

    如果大家有好的想法,可以微信:541002349 讨论。

    也欢迎关注公众号“ITman彪叔”,接收更多消息。


    起源地下载网 » 基于路径集合的三维动画链

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元