0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

HT for Web (Hightopo) 使用心得(5)- 動畫的實現(xiàn)

圖撲-數(shù)字孿生 ? 來源:圖撲-數(shù)字孿生 ? 作者:圖撲-數(shù)字孿生 ? 2023-11-29 11:04 ? 次閱讀

其實,在 HT for Web 中,有多種手段可以用來實現(xiàn)動畫。我們這里仍然用直升機為例,只是更換了場景。增加了巡游過程。

使用 HT 開發(fā)的一個簡單網(wǎng)頁直升機巡邏動畫(Hightopo 使用心得(5))

這里主要用到的動畫實現(xiàn)方式有三種:

setInterval

ht.Default.startAnim()

DataModel.addScheduleTask(task)

場景搭建

具體3D場景的相關概念請參考《Hightopo 使用心得(4)- 3D 場景 Graph3dView 與 Obj 模型》。

這里的主要工作分為:3D 場景配置以及模型加載。其中 3D 場景部分的設置代碼如下:

this.g3d = new ht.graph3d.Graph3dView();

this.g3d.setGridVisible(true);

this.g3d.setGridSize(5000);

this.g3d.setGridGap(2000);

this.g3d.setNear(10)

this.g3d.setFar(10000000)

this.g3d.addToDOM();

this.dataModel = this.dm = this.g3d.dm();

為了給直升機搭建一個逼真的環(huán)境。這里我們增加了一個山體模型。另外,由于直升機機體與螺旋槳模型是分開的,因此需要分別加載并調(diào)整其位置讓二者合并成一個模型。

// 加載山體模型

this.mountains = await this.createObj(MODELS.MOUNTAINS.name, MODELS.MOUNTAINS.obj, MODELS.MOUNTAINS.mtl);

this.mountains.s('3d.selectable',false);

this.mountains.s('shape3d.scaleable',true);

this.mountains.setScale3d([0.01, 0.1, 0.01]);

this.mountains.setElevation(1800); // 讓山體在地面以上

// 分別加載直升機及螺旋槳模型

this.helicopterNode = await this.createObj(MODELS.HELICOPTER.name, MODELS.HELICOPTER.obj, MODELS.HELICOPTER.mtl);

this.propellerNode = await this.createObj(MODELS.PROPELLER.name, MODELS.PROPELLER.obj, MODELS.PROPELLER.mtl);

// 由于默認創(chuàng)建 Node 的時候,其錨點是在 [0.5, 0.5, 0.5],位置是在 [0, 0, 0]。導致模型并不在水平面以上。

let size3d = this.helicopterNode.getSize3d(); // 獲取直升機模型的 [長,寬,高]

let height = size3d[1]; // 獲取模型高度

this.helicopterNode.setPosition3d([0, height/2, 0]); // 將直升機放到地面上

this.propellerNode.setRotation3d([0.10506443461595279, 4.550746858974086, -0.007825951889059535]); // 讓螺旋槳水平

this.propellerNode.setPosition3d([0, 215, -99.00152946490829]); // 將螺旋槳放到直升機上

this.propellerNode.setHost(this.helicopterNode); // 螺旋槳吸附到直升機上

this.helicopterNode.p3(0,2000,0); // 直升機

wKgZomVmqlGARY9wAAt-S89mkn8765.png

螺旋槳動畫 - setInterval

螺旋槳動畫比較簡單,我們在《Hightopo 使用心得(4)- 3D 場景 Graph3dView 與 Obj 模型_CodingInProgress的博客-CSDN博客》中已經(jīng)提過。其本質(zhì)是通過不斷地修改螺旋槳節(jié)點在豎直方向(Y 軸)的角度。

/**

* 螺旋槳旋轉(zhuǎn)動畫

*

*/

startPropellerAnim(node) {

setInterval(() => {

const r3 = node.getRotation3d();

node.setRotation3d([r3[0], r3[1] + 0.4, r3[2]]); // 繞 Y 軸旋轉(zhuǎn)

}, 20);

}

創(chuàng)建直升機巡游路徑

有了直升機及環(huán)境,我們需要讓直升機動起來。例如在這里,我們計劃讓直升機圍繞山體巡邏。這里該如何實現(xiàn)呢?

在 HT for Web 官方手冊中,其提供了一種實現(xiàn)方式,我們這里稍微加以改造便可讓直升機圍繞山體巡邏。

wKgaomVmqlKAEoGrAAf-OHJWVgU936.gif

在代碼層面,我們創(chuàng)建了一條三維線段(Polyline)。該線段實現(xiàn)的是一個圓環(huán),懸浮在山體上面。有了這條路徑,直升機便可沿著該路徑前進實現(xiàn)巡游動畫。

polyline的形狀主要由points和segments這兩個屬性描述。二者都是數(shù)組。其中 points 可以理解成組成 polyline 所要用到的點集合,而 segments 數(shù)組主要用來定義如何使用前面的點來組成 polyline。

points 中的每一項為 {x,y,e} 格式,需要注意的是,這里代表高度的是 e(elevation),而不是 y。

segments 數(shù)組里面有5種值。分別為:

1: moveTo,占用1個點信息,代表一個新路徑的起點

2: lineTo,占用1個點信息,代表從上次最后點連接到該點

3: quadraticCurveTo,占用2個點信息,第一個點作為曲線控制點,第二個點作為曲線結束點

4: bezierCurveTo,占用3個點信息,第一和第二個點作為曲線控制點,第三個點作為曲線結束點

5: closePath,不占用點信息,代表本次路徑繪制結束,并閉合到路徑的起始點

/**

* 創(chuàng)建直升機巡游路徑

*

* @memberof Index3d

*/

createPath() {

this.g3d.setDashDisabled(false); // 顯示虛線

let height = 2000; // 線段離地高度

let dataModel = this.dataModel;

let polyline = this.polyline = new ht.Polyline();

polyline.setThickness(5); // 線段粗細

polyline.s({

'shape3d.image': 'assets/flow.png', // 貼圖

"shape3d": "cylinder", // polyline類型,這里是圓柱。也可以是

'repeat.uv.length': 400, // 貼圖寬度

'shape3d.resolution': 1600, // 管線分辨率,分辨率越高越平滑

});

dataModel.add(polyline);

// 起始點

const points = [{

x: -15000,

y: 0,

e: height,

}];

const segments = [1];

// 二次曲線,占用兩個點。生成一條弧線。下同。

points.push({

x: -15000,

y: -15000,

e: height

});

points.push({

x: 0,

y: -15000,

e: height

});

segments.push(3);

points.push({

x: 15000,

y: -15000,

e: height

});

points.push({

x: 15000,

y: 0,

e: height

});

segments.push(3);

points.push({

x: 15000,

y: 15000,

e: height

});

points.push({

x: 0,

y: 15000,

e: height

});

segments.push(3);

points.push({

x: -15000,

y: 15000,

e: height

});

points.push({

x: -15000,

y: 0,

e: height,

});

segments.push(3);

polyline.setPoints(points);

polyline.setSegments(segments);

polyline.setAnchorElevation(0)

}

直升機巡游動畫 - ht.Default.startAnim

接下來,我們需要讓直升機沿著巡游路徑前進。在實現(xiàn)的時候,我們使用了 ht.Default.startAnim() 方法。該方法我們在前幾篇文章中都用過,這里就不再詳細介紹。

wKgZomVmqlOAb6jnAArqNcgMBts517.png

ht.Default.startAnim() 會執(zhí)行 duration 毫秒,在執(zhí)行過程中,其會自動計算所需要的幀數(shù)并在每一幀都調(diào)用一次action 方法。也就是說,如果我們想讓直升機 40 秒圍繞路徑飛行一圈,我們只需要將 duration 設置成40*1000 毫秒,并且在每一幀拿到當前時刻 polyline 上的點的坐標及方向。同時,使用該坐標與方向設置直升機位置及朝向就可以實現(xiàn)巡游動畫。

這里面比較關鍵的一個方法是 g3d.getLineOffset(polyline, length * v) 。該方法會返回一個對象:{point: p.M…h(huán).Vector3, tangent: p.M…h(huán).Vector3}。其分別代表當前時刻 polyline 上的點的坐標及放向。根據(jù)這兩個值,我們可以進一步配置直升機的位置和朝向。

/**

* 直升機沿著巡游路徑飛行

*

* @param {number} [duration=40 * 1000]

* @memberof Index3d

*/

startFly(duration = 40 * 1000) {

const {

g3d,

polyline

} = this;

/** 獲取巡游路徑總長度 */

let length = g3d.getLineLength(polyline);

const params = {

delay: 0,

duration,

easing: (t) => {

return t;

},

action: (v, t) => {

let offset = g3d.getLineOffset(polyline, length * v),

point = offset.point,

px = point.x,

py = point.y + 200, // 讓直升機高于polyline

pz = point.z,

tangent = offset.tangent,

tx = tangent.x,

ty = tangent.y,

tz = tangent.z;

this.helicopterNode.p3(px, py, pz);

this.helicopterNode.lookAt([px + tx, py + ty, pz + tz], 'back'); // 一個模型有6個面,這里需要確定機頭處于哪個面

// 視角盯住直升機

if (this._cameraType == 1) {

g3d.setCenter(px, py, pz);

} else if (this._cameraType == 2) { // Camera跟隨直升機運動

g3d.setEye(px - tx * 1800 + 1000, py - ty * 1800 + 1000, pz - tz * 1800); // 讓鏡頭高于直升機并在尾部進行觀察

g3d.setCenter(px, py, pz);

}

this.helicopterNode.a('angle', v * Math.PI * 120);

},

finishFunc: () => {

ht.Default.startAnim(params);

}

};

ht.Default.startAnim(params);

}

管道流動動畫 - DataModel.addScheduleTask()

實現(xiàn)管道流動的動畫有多種方式,其本質(zhì)是定期改變管道的貼圖偏移。

wKgaomVmqlOADRQtAArdggdCPLE722.gif

這里我們采用DataModel#addScheduleTask(task)實現(xiàn)流動動畫。DataModel#addScheduleTask(task)實際上是添加了一個調(diào)度任務。由于該方法是在 DataModel 上執(zhí)行,因此在每次執(zhí)行的時候,DataModel 里面的每個 Data 都會被調(diào)用。我們可以在 action 參數(shù)里面對 Data 進行過濾。DataModel#addScheduleTask(task)方法的參數(shù)task為json對象,可指定如下屬性:

interval:間隔毫秒數(shù),默認值為10

enabled:是否啟用開關,默認為true

beforeAction:調(diào)度開始之前的動作函數(shù)

action:間隔動作函數(shù),對DataModel上的每個data節(jié)點都會執(zhí)行一次action操作

afterAction:調(diào)度結束之后的調(diào)度函數(shù)

另外,可以用DataModel#removeScheduleTask(task)刪除調(diào)度任務,其中task為以前添加過的調(diào)度任務對象。

/**

* 通過DataModel的addScheduleTask實現(xiàn)流動效果

*

* @memberof Index3d

*/

addScheduleTasks() {

const task = {

interval: 50, // 間隔毫秒數(shù),默認值為10

enabled: true, // 是否啟用開關,默認為true

beforeAction: () => {}, // 調(diào)度開始之前的動作函數(shù)

afterAction: () => {}, // 調(diào)度結束之后的調(diào)度函數(shù)

action: (data) => { // 間隔動作函數(shù),對DataModel上的每個data節(jié)點都會執(zhí)行一次action操作

if (data.getClassName() == 'ht.Polyline') {

const offset = (data.s('shape3d.uv.offset') || [0,0]);

data.s('shape3d.uv.offset', [offset[0] + 0.1, offset[1]]);

}

}

};

this.dataModel.addScheduleTask(task);

// this.dataModel.removeScheduleTask(task); // 刪除調(diào)度任務

}

這里我們只是舉例介紹一下DataModel#addScheduleTask(task)的用法。對于一個 DataModel 中大部分 Data 都需要動畫的時候,可以考慮使用該方法。

在代碼執(zhí)行的時候,我們可以選擇把巡游路徑隱藏。這樣看起來直升機就是沿著一個圓形持續(xù)巡游。

hidePath() {

this.polyline.s('3d.visible', false);

}

總結

本文介紹了如何通過代碼實現(xiàn)一個直升機繞山巡游的動畫,包括創(chuàng)建路徑和實現(xiàn)直升機的飛行動畫。另外,還介紹了如何通過DataModel#addScheduleTask(task)實現(xiàn)流動效果的動畫。讀完本文,你將了解到如何使用 HT for Web 實現(xiàn)各種動畫效果。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
收藏 人收藏

    評論

    相關推薦

    HT for Web (Hightopo) 使用心得(1)- 基本概念

    本章主要介紹了 HT for Web 中的一些基本概念,包括:基礎數(shù)據(jù) ht.Data、數(shù)據(jù)模型 ht.DataModel 和選擇模型 ht
    的頭像 發(fā)表于 09-11 10:45 ?995次閱讀
    <b class='flag-5'>HT</b> for <b class='flag-5'>Web</b> (<b class='flag-5'>Hightopo</b>) 使<b class='flag-5'>用心得</b>(1)- 基本概念

    HT for Web (Hightopo) 使用心得(3)- 吸附與錨點

    船錨所在點,只不過船的錨點在船外面,而 HT 節(jié)點的錨點通常在其中心。并且這里的錨鏈是剛性的不能彎曲。
    的頭像 發(fā)表于 10-12 10:44 ?957次閱讀
    <b class='flag-5'>HT</b> for <b class='flag-5'>Web</b> (<b class='flag-5'>Hightopo</b>) 使<b class='flag-5'>用心得</b>(3)- 吸附與錨點

    HT for Web (Hightopo) 使用心得(4)- 3D 場景 Graph3dView 與 Obj 模型

    這里我們通過代碼建立一個 3D 場景并添加一個 Obj 模型來介紹一下 HT for Web 在 3D 場景和模型加載方面的使用。
    的頭像 發(fā)表于 11-20 11:05 ?708次閱讀
    <b class='flag-5'>HT</b> for <b class='flag-5'>Web</b> (<b class='flag-5'>Hightopo</b>) 使<b class='flag-5'>用心得</b>(4)- 3D 場景 Graph3dView 與 Obj 模型

    濾波電容的使用心得

    圖說濾波電容的使用心得,非常詳細,不信你還不懂~
    發(fā)表于 07-18 15:23

    關于Spartan6板子的使用心得

    給大家分享一下關于Spartan6板子的使用心得
    發(fā)表于 04-30 07:03

    TFT LCD使用心得

    TFT LCD使用心得體會的原因是,最近一段時間工作上一直在使用TFT LCD,主要是3.5寸LCD,以SAMSUNG的LTV350QV及其一些臺灣的兼容產(chǎn)品為主。工作的內(nèi)容就是把這些屏在我們的產(chǎn)品上應用起
    發(fā)表于 10-16 13:04 ?45次下載

    詳細談談TFT LCD 的使用心得

    深入談談TFT LCD 的使用心得最近一段時間工作上一直在使用TFT LCD,主要是3、5 寸LCD,以SAMSUNG 的LTV350QV 及其一些臺灣的兼容產(chǎn)品為主。工作的內(nèi)容就是把這些屏在我們的產(chǎn)品上
    發(fā)表于 03-18 17:49 ?3次下載

    ADXL345芯片使用心得

    ADXL345芯片使用心得,介紹使用傳感器過程的使用體會
    發(fā)表于 05-11 11:08 ?23次下載

    數(shù)字溫濕度傳感器DHT11使用心得

    一點溫濕度傳感器DHT11使用心得
    發(fā)表于 04-14 15:35 ?7次下載

    Django教程之Django的使用心得詳細資料免費下載

    本文檔的主要內(nèi)容詳細介紹的是Django教程之Django的使用心得詳細資料免費下載。
    發(fā)表于 10-17 18:03 ?11次下載
    Django教程之Django的使<b class='flag-5'>用心得</b>詳細資料免費下載

    合泰單片機使用心得 (轉(zhuǎn))

    合泰單片機使用心得 合泰單片機是臺灣芯片,集成開發(fā)環(huán)境為HT-3000。大陸這邊的芯片代理商是盛群半導體有限公司,官網(wǎng)上的程序用例都是由匯編編寫的,當然也對C語言很好的支持,是標準C的子集。在工作中
    發(fā)表于 12-02 20:36 ?12次下載
    合泰單片機使<b class='flag-5'>用心得</b> (轉(zhuǎn))

    智慧服裝工廠電子看板試用心得

    智慧服裝工廠電子看板試用心得實現(xiàn)了企業(yè)生產(chǎn)的進度實時監(jiān)控、現(xiàn)場拉式生產(chǎn)、生產(chǎn)節(jié)拍平衡和異常情況的反饋功能。而接下來我們主要討論的是智慧服裝工廠電子看板試用心得在生產(chǎn)線與倉庫之間的物料配送體系,要談到這個物料配送問題,則要首先考慮
    的頭像 發(fā)表于 02-17 18:02 ?993次閱讀
    智慧服裝工廠電子看板試<b class='flag-5'>用心得</b>

    使用Raspberry Pi和Arduino實現(xiàn)Web控制的LED動畫

    電子發(fā)燒友網(wǎng)站提供《使用Raspberry Pi和Arduino實現(xiàn)Web控制的LED動畫.zip》資料免費下載
    發(fā)表于 07-03 14:52 ?0次下載
    使用Raspberry Pi和Arduino<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>Web</b>控制的LED<b class='flag-5'>動畫</b>

    HT for Web (Hightopo) 使用心得(2)- 2D 圖紙、節(jié)點、連線 與基本動畫

    概括來說,用 HT for Web 做可視化主要分為兩部分,也就是 2D 和 3D。這兩部分需要單獨創(chuàng)建。在它們被創(chuàng)建完成后,我們再把它們集成到一起。 HT for Web 的 2D
    的頭像 發(fā)表于 09-21 10:52 ?830次閱讀
    <b class='flag-5'>HT</b> for <b class='flag-5'>Web</b> (<b class='flag-5'>Hightopo</b>) 使<b class='flag-5'>用心得</b>(2)- 2D 圖紙、節(jié)點、連線 與基本<b class='flag-5'>動畫</b>

    HT for Web并力ARMxy工業(yè)計算機實現(xiàn)數(shù)字化轉(zhuǎn)型可視化解決方案

    ,用戶可以輕松設計出直觀的監(jiān)控場景,實現(xiàn)對工業(yè)過程的實時數(shù)據(jù)展示和交互控制。而ARMxy系列產(chǎn)品以其強大的數(shù)據(jù)處理能力和靈活的IO配置,精準響應生產(chǎn)需求,驅(qū)動自動化流程,助力企業(yè)實現(xiàn)數(shù)字化轉(zhuǎn)型。 一、HT for
    的頭像 發(fā)表于 08-28 16:17 ?319次閱讀
    <b class='flag-5'>HT</b> for <b class='flag-5'>Web</b>并力ARMxy工業(yè)計算機<b class='flag-5'>實現(xiàn)</b>數(shù)字化轉(zhuǎn)型可視化解決方案