鍵幀軌道的原理、用法與離散插值機(jī)制)
three.js BooleanKeyframeTrack布爾關(guān)鍵幀軌道的原理、用法與離散插值機(jī)制【免費(fèi)下載鏈接】three.jsJavaScript 3D Library.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/th/three.jsBooleanKeyframeTrack是 three.js 動(dòng)畫(huà)系統(tǒng)中專(zhuān)門(mén)承載布爾型關(guān)鍵幀數(shù)據(jù)的軌道類(lèi)型繼承自KeyframeTrack。它沒(méi)有插值參數(shù)——布爾值只能離散切換因此在源碼層面其默認(rèn)插值被固定為InterpolateDiscrete。讀完本文你將掌握該軌道的構(gòu)造方式、三個(gè)被覆寫(xiě)的原型屬性、它在動(dòng)畫(huà)序列AnimationClip/AnimationMixer中的典型應(yīng)用以及其 JSON 序列化與反序列化的完整鏈路。在軌道家族中的定位three.js 的動(dòng)畫(huà)系統(tǒng)通過(guò)軌道Track 片段Clip 混合器Mixer三層結(jié)構(gòu)組織關(guān)鍵幀數(shù)據(jù)。KeyframeTrack派生出六個(gè)子類(lèi)分別對(duì)應(yīng)不同的值類(lèi)型位于 src/animation/tracks/ 目錄軌道類(lèi)值類(lèi)型典型動(dòng)畫(huà)目標(biāo)NumberKeyframeTrack標(biāo)量數(shù)字半徑、強(qiáng)度等單一數(shù)值VectorKeyframeTrack2/3/4 維向量位置、縮放QuaternionKeyframeTrack四元數(shù)旋轉(zhuǎn)ColorKeyframeTrackRGB 顏色顏色屬性StringKeyframeTrack字符串切換資源名等BooleanKeyframeTrack布爾值可見(jiàn)性.visible等開(kāi)關(guān)屬性官方 API 文檔docs/pages/BooleanKeyframeTrack.html.md將其概括為一句話A track for boolean keyframe values用于布爾關(guān)鍵幀值的軌道。布爾值是典型的不可插值類(lèi)型——它既不能做線性混合也沒(méi)有平滑過(guò)渡的概念因此這個(gè)軌道類(lèi)是整個(gè)家族中結(jié)構(gòu)最簡(jiǎn)、約束最特殊的一個(gè)。構(gòu)造函數(shù)基本用法new BooleanKeyframeTrack( name, times, values );與多數(shù)兄弟類(lèi)不同構(gòu)造函數(shù)只有三個(gè)參數(shù)namestring軌道名稱。軌道名會(huì)被PropertyBinding解析用于定位被動(dòng)畫(huà)對(duì)象上的具體屬性例如.visible、mesh.material.transparent或骨骼、morph target 路徑timesArray 關(guān)鍵幀時(shí)間列表按升序排列valuesArray 與times一一對(duì)應(yīng)的關(guān)鍵幀值列表。沒(méi)有第四個(gè)interpolation參數(shù)。這一點(diǎn)與KeyframeTrack基類(lèi)構(gòu)造函數(shù)constructor( name, times, values, interpolation )見(jiàn) KeyframeTrack.js形成對(duì)比官方文檔也明確說(shuō)明This keyframe track type has nointerpolationparameter because the interpolation is always discrete.該軌道類(lèi)型沒(méi)有interpolation參數(shù)因?yàn)椴逯凳冀K是離散的。從源碼看其構(gòu)造函數(shù)只是把參數(shù)原樣透?jìng)鹘o基類(lèi)BooleanKeyframeTrack.jsconstructor( name, times, values ) { super( name, times, values ); }基類(lèi)構(gòu)造時(shí)執(zhí)行的驗(yàn)證與類(lèi)型轉(zhuǎn)換基類(lèi)KeyframeTrack構(gòu)造函數(shù)KeyframeTrack.js在創(chuàng)建實(shí)例時(shí)做了三件事均適用于布爾軌道參數(shù)校驗(yàn)name為undefined時(shí)拋出THREE.KeyframeTrack: track name is undefinedtimes為undefined或空數(shù)組時(shí)拋出no keyframes in track named ...L31-L32。緩沖區(qū)類(lèi)型轉(zhuǎn)換times通過(guò)AnimationUtils.convertArray轉(zhuǎn)換為本類(lèi)TimeBufferTypeFloat32Arrayvalues則轉(zhuǎn)換為ValueBufferType。由于布爾軌道覆寫(xiě)了ValueBufferType Array其values最終是一個(gè)普通 JS 數(shù)組而非 TypedArrayL48-L55。插值初始化執(zhí)行this.setInterpolation( interpolation || this.DefaultInterpolation )。布爾軌道不傳插值參數(shù)因此固定使用DefaultInterpolation即InterpolateDiscrete。單元測(cè)試 test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js 使用的參數(shù)正是文檔中最典型的一組const parameters { name: .visible, times: [ 0, 1 ], values: [ true, false ], }; const object new BooleanKeyframeTrack( parameters.name, parameters.times, parameters.values );.visible這個(gè)軌道名表明該軌道最常見(jiàn)的用途是驅(qū)動(dòng)對(duì)象的可見(jiàn)性開(kāi)關(guān)。三個(gè)被覆寫(xiě)的原型屬性BooleanKeyframeTrack的全部個(gè)性都體現(xiàn)在對(duì)基類(lèi)三個(gè)原型屬性的覆寫(xiě)上官方文檔逐一列出了它們與 KeyframeTrack 的覆寫(xiě)關(guān)系屬性默認(rèn)值基類(lèi)默認(rèn)值源碼位置.ValueTypeNameboolBooleanKeyframeTrack.js#L35.ValueBufferTypeArray普通數(shù)組Float32ArrayBooleanKeyframeTrack.js#L43.DefaultInterpolationInterpolateDiscreteInterpolateLinearBooleanKeyframeTrack.js#L51ValueTypeName bool值類(lèi)型的標(biāo)識(shí)符。它一方面用于錯(cuò)誤/警告信息的拼接如 unsupported interpolation for bool keyframe track named ...另一方面是 JSON 序列化時(shí)type字段的來(lái)源見(jiàn)下文。ValueBufferType ArrayTypedArray 中沒(méi)有布爾類(lèi)型因此布爾軌道只能把值存在普通數(shù)組里。這也解釋了為什么基類(lèi)validate()中的 NaN 檢查針對(duì) TypedArray對(duì)布爾軌道天然不適用。DefaultInterpolation InterpolateDiscrete默認(rèn)插值為離散。除了這三個(gè)文檔中列出的屬性源碼里還有兩行同樣關(guān)鍵的靜默設(shè)置L52-L53BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear undefined; BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth undefined;即布爾軌道主動(dòng)把線性與平滑兩種插值的工廠方法置為undefined。這與構(gòu)造函數(shù)不接收interpolation參數(shù)是同一設(shè)計(jì)決策的兩面——下面專(zhuān)門(mén)分析其機(jī)制。為什么插值恒為離散源碼層面的機(jī)制three.js 的插值由插值器工廠方法實(shí)現(xiàn)?;?lèi)提供四種工廠方法InterpolantFactoryMethodDiscrete / Linear / Smooth / BezierKeyframeTrack.js#L113-L170。setInterpolation( interpolation )按傳入常量選擇對(duì)應(yīng)工廠方法并賦給this.createInterpolantL178-L239。如果所選工廠方法為undefined對(duì)布爾軌道而言就是 Linear 或 Smooth基類(lèi)的回退邏輯是若該軌道此前從未設(shè)置過(guò)createInterpolant且請(qǐng)求的插值不是默認(rèn)插值則強(qiáng)制回退到默認(rèn)插值并打印警告KeyframeTrack: unsupported interpolation for bool keyframe track named ...L210-L231因此對(duì)BooleanKeyframeTrack而言任何試圖使用 Linear/Smooth 的路徑都會(huì)被靜默糾正為 Discrete。真正執(zhí)行求值的是DiscreteInterpolantsrc/math/interpolants/DiscreteInterpolant.js。它的核心方法只有三行interpolate_( i1 /*, t0, t, t1 */ ) { return this.copySampleValue_( i1 - 1 ); }語(yǔ)義非常直白取參數(shù)位置之前最近那個(gè)關(guān)鍵幀的采樣值原樣返回——不做任何混合。這正是布爾數(shù)據(jù)唯一合理的插值方式值在關(guān)鍵幀時(shí)刻發(fā)生跳變兩次跳變之間保持恒定。再看混合階段。當(dāng)AnimationMixer為軌道創(chuàng)建屬性混合器時(shí)PropertyMixer按類(lèi)型分派混合函數(shù)PropertyMixer.js#L51-L82case string: case bool: mixFunction this._select; // additive is not relevant for non-numeric types mixFunctionAdditive this._select; ... this.buffer new Array( valueSize * 5 );布爾類(lèi)型與字符串一樣走_(dá)select按權(quán)重選擇而非數(shù)值型的_lerp且注釋明確指出additive 對(duì)非數(shù)值類(lèi)型無(wú)意義——布爾軌道在加性混合模式下退化為普通選擇。此外在 AnimationUtils.js#L265 的處理路徑中bool與string類(lèi)型會(huì)被顯式跳過(guò)從源碼結(jié)構(gòu)看這體現(xiàn)了框架在需要數(shù)值運(yùn)算的場(chǎng)景中對(duì)非數(shù)值軌道的統(tǒng)一豁免。典型實(shí)戰(zhàn)動(dòng)畫(huà)切換對(duì)象可見(jiàn)性結(jié)合上述機(jī)制一個(gè)完整的最小用例如下依賴three主模塊import * as THREE from three; // 1. 布爾軌道0s 時(shí)可見(jiàn)2s 時(shí)隱藏4s 時(shí)重新可見(jiàn) const track new THREE.BooleanKeyframeTrack( .visible, // 軌道名解析到目標(biāo)對(duì)象的 visible 屬性 [ 0, 2, 4 ], // times [ true, false, true ] // values普通 JS 布爾值 ); // 2. 組裝成動(dòng)畫(huà)片段duration 可傳 -1 表示由軌道自動(dòng)推算 const clip new THREE.AnimationClip( blink, -1, [ track ] ); // 3. 為場(chǎng)景中的對(duì)象創(chuàng)建混合器并播放 const mixer new THREE.AnimationMixer( mesh ); const action mixer.clipAction( clip ); action.play(); // 4. 渲染循環(huán)中推進(jìn)時(shí)間 function animate( dt ) { mixer.update( dt ); // ... }行為預(yù)測(cè)由DiscreteInterpolant的取前值語(yǔ)義決定t ∈ [0, 2)時(shí)mesh.visible為truet ∈ [2, 4)時(shí)為falset ≥ 4后回到true。注意切換發(fā)生在關(guān)鍵幀時(shí)刻而不是漸變過(guò)去——這是離散插值的固有特性。由于布爾軌道getValueSize()為 1values.length / times.lengthtimes與values必須嚴(yán)格等長(zhǎng)否則基類(lèi)validate()會(huì)報(bào) Invalid value size in track。序列化與還原bool 類(lèi)型名如何貫穿 JSON 鏈路布爾軌道的bool類(lèi)型名在 JSON 往返鏈路中扮演樞紐角色序列化KeyframeTrack.toJSON( track )KeyframeTrack.js#L68-L104輸出{ name, times, values, type: track.ValueTypeName }。由于布爾軌道的插值恒等于默認(rèn)值InterpolateDiscreteinterpolation ! track.DefaultInterpolation判斷不成立JSON 中不會(huì)出現(xiàn)interpolation字段——這再次印證插值固定的設(shè)計(jì)。反序列化AnimationClip內(nèi)部按type字段查找軌道類(lèi)映射表中有明確分支AnimationClip.js#L439-L442case bool: case boolean: return BooleanKeyframeTrack;即bool與boolean兩種寫(xiě)法都能正確還原為BooleanKeyframeTrack無(wú)法識(shí)別的類(lèi)型名會(huì)拋出Unsupported typeName錯(cuò)誤??寺』?lèi)clone()KeyframeTrack.js#L587-L600使用this.constructor重建實(shí)例并直接拷貝createInterpolant工廠方法對(duì)布爾軌道而言克隆后仍是離散插值的BooleanKeyframeTrack。從基類(lèi)繼承的實(shí)用方法除上述專(zhuān)屬定義外BooleanKeyframeTrack實(shí)例完整繼承了基類(lèi)的軌道編輯方法均可鏈?zhǔn)秸{(diào)用并返回thisshift( timeOffset )整體平移關(guān)鍵幀時(shí)間KeyframeTrack.js#L287scale( timeScale )按比例縮放時(shí)間便于幀-秒換算L311;trim( startTime, endTime )裁剪區(qū)間外的關(guān)鍵幀且至少保留一個(gè)關(guān)鍵幀L339optimize()移除與相鄰關(guān)鍵幀等值的冗余幀。對(duì)布爾軌道這類(lèi)開(kāi)關(guān)序列尤為有效例如true, true, true, false, false可壓縮為true, falseL469-L579validate()校驗(yàn)值尺寸、時(shí)間有序性與數(shù)值合法性L387。這些方法在 docs/pages/KeyframeTrack.html.md 的基類(lèi)文檔中有完整說(shuō)明在編輯布爾軌道時(shí)間軸時(shí)同樣適用。小結(jié)BooleanKeyframeTrack是 three.js 動(dòng)畫(huà)體系中非數(shù)值軌道的代表以最小的源碼體量55 行完成了三處屬性覆寫(xiě)ValueTypeName、ValueBufferType、DefaultInterpolation與兩處插值工廠禁用從而在構(gòu)造、插值、混合、序列化各環(huán)節(jié)都強(qiáng)制走離散路徑。對(duì)于需要程序化驅(qū)動(dòng).visible、transparent等開(kāi)關(guān)型屬性的動(dòng)畫(huà)配合AnimationClip與AnimationMixer即可實(shí)現(xiàn)確定性的狀態(tài)跳變控制?!久赓M(fèi)下載鏈接】three.jsJavaScript 3D Library.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/th/three.js創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考