基於路徑集合的三維動畫鏈

1、配置路徑數據2、創建動畫鏈2.1、rotationAniamte2.2、moveAnimate2.3、動畫鏈式銜接3、動畫鏈效果

目前數據信息可視化的發展趨勢越來越快,緯度寬廣、數量龐大、結構複雜的數據展示僅僅只依靠二維平面圖表已經不能滿足了。爲了更加清晰,快速的認知和理解一份數據,構建基於現實的三維虛擬可視化效果,被廣泛應用到各行業中,迅速成爲信息數字化管理的重要組成部分。

三維場景還原了現實的虛擬效果,而各種各樣的動畫則賦予其更加飽滿、靈動的視覺衝擊。基於路徑集合的三維動畫鏈,它充實了場景中元素的動畫效果,接下來我會具體介紹動畫鏈的實現過程。

1、配置路徑數據

此次示例中模型均採用gltf格式,以上圖場景中小車爲例,在模型加載完成後,我們定義配置好一系列的路徑點(animatePath),讓小車按照該路徑執行動畫。

 1scene.loadGLTF('./static/gltf/car1/1.gltf', {
2  generateTangenttrue,
3  useIBLWhenMissingTexturetrue,
4  loadTexturetrue,
5}).then((data) => {
6  const element = data.root;
7  element.scale = [0.10.10.1];
8  element.ry = Math.PI;
9  element.position = [981.5-125];
10
11  const { y } = element;
12  const animatePath = [
13    [98, y, -135],
14    [50, y, -135],
15    [10, y, -95],
16    [-30, y, -125]
17  ]
18
19  // 創建動畫鏈
20  element.animate = this.createPathAnimates(element, animatePath, () => {
21    // 動畫鏈結束後的處理
22    ... ...
23  });
24
25  element.animate.play();
26})

其中animatePath的配置,爲了滿足不同的場景需求,我們可以通過各種方式去實現它的定義;
例如:

  • 在場景中通過可視化的打點操作形成路徑

  • 在該場景元素的屬性面板中,進行JSON數據的配置

  • 對於精準規範的路徑,可以通過接口返回的數據處理

  • … …

2、創建動畫鏈

實現小車路徑集合的動畫鏈,在遍歷路徑的時候,需要注意兩個過程,一個是小車的moveAnimate(小車沿路徑移動的動畫),另一個則是每一次moveAniamte之前的rotationAniamte(小車在下一段路徑動畫前的朝向動畫);

 1createPathAnimates(element, points, done) {
2  // 聲明一個有序的動畫集合,方便後面進行動畫鏈處理
3  const animates = [];
4  if (points && points.length > 0) {
5    // 獲取小車的初始位置和旋轉角度
6    let { x, y, z } = element;
7    let angle = element.ry;
8    for (let i = 0, len = points.length; i < len; i++) {
9      const point = points[i];
10      const x1 = point[0];
11      const z1 = point[2];
12      // 計算下一段與上一段之間的角度,創建rotateAnimate 
13      const rotate = Math.atan2(-(z1 - z), x1 - x);
14      const rotateAnimate = this.createRotateAnimate(element, rotate, angle);
15      if (rotateAnimate) {
16        animates.push(rotateAnimate);
17        angle = rotateAnimate.toAngle;
18      }
19      // 創建moveAnimate 
20      const moveAnimate = this.createMoveAnimate(element, [x, z], [x1, z1]);
21      if (moveAnimate) {
22        animates.push(moveAnimate);
23        x = x1;
24        z = z1;
25      }
26    }
27  }
28
29  // done爲動畫鏈接結束後的回調處理函數
30  animates[animates.length - 1].onDone = done;
31  let animate;
32  for (let i = 0, len = animates.length; i < len; i++) {
33    if (i > 0) {
34      animates[i - 1].chain(animates[i]);
35    } else {
36      animate = animates[i];
37    }
38  }
39
40  return animate;
41}

2.1、rotationAniamte

通過Math.atan2()方法,獲取相對的偏移弧度:


與小車的當前弧度進行比較創建rotationAnimate:


 1createRotateAnimate(element, toAngle, angle) {
2  if (toAngle !== angle) {
3    if (toAngle - angle > Math.PI) {
4      toAngle -= Math.PI * 2;
5    }
6    if (toAngle - angle < -Math.PI) {
7      toAngle += Math.PI * 2;
8    }
9  }
10  const rotateAnimate = new Animate({
11    from: angle,
12    to: toAngle,
13    type'number',
14    durMath.abs(toAngle - angle) * 300,
15    easing'easeNone',
16    onPlay() {
17      element.animate = this;
18    },
19    onUpdate(value) {
20      element.ry = value + (Math.PI / 2);
21    },
22  });
23  rotateAnimate.toAngle = toAngle;
24  return rotateAnimate;
25}

2.2、moveAnimate

通過上一段與下一段的point創建moveAniamte:

 1createMoveAnimate(element, [x, z], [x1, z1]) {
2  return new Animate({
3    from: [x, z],
4    to: [x1, z1],
5    type'point',
6    durMath.sqrt((x1 - x) ** 2 + (z1 - z) ** 2) * 100 || 100,
7    easing'easeNone',
8    onUpdate(value) {
9      const [x, z] = value;
10      element.position = vec3.fromValues(x, element.y, z);
11    },
12  });
13}

2.3、動畫鏈式銜接

處理好對應的rotationAniamte和moveAnimate後,採用動畫實例對象的chain方法進行鏈式銜接,最終的動畫實力對象就能夠實現我們的動畫效果了,同時可以處理動畫鏈結束後的其他操作:

 1createPathAnimates(element, points, done) {
2  // 聲明一個有序的動畫集合,方便後面進行動畫鏈處理
3  const animates = [];
4  ... ...
5  // done爲動畫鏈接結束後的回調處理函數
6  animates[animates.length - 1].onDone = done;
7  let animate;
8  for (let i = 0, len = animates.length; i < len; i++) {
9    if (i > 0) {
10      animates[i - 1].chain(animates[i]);
11    } else {
12      animate = animates[i];
13    }
14  }
15
16  return animate;
17}

3、動畫鏈效果

以上述示例來說,最終小車的動畫效果:

至此,一個基於路徑集合的動畫鏈就完成了,實現的原理也並不複雜;有了這樣的動畫鏈機制,我們就可以實現以路徑爲核心的不同的動畫效果,廣泛應用到各種動畫需求的場景當中。

例如,倉庫中的作業流程:

1.gif


除了把路徑動畫鏈應用到場景元素上,我們還可以應用到三維場景的鏡頭上面,這樣一來就能夠實現巡航的動畫效果:

    

2.gif


本文分享自微信公衆號 - ITman彪叔(gh_298594c8da3a)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章