欧美日韩精品一区二区在线线,一级无码在线收看,精品国产高清91,久久精品欧美电影

# 組件

組件Component用于實(shí)現(xiàn)xr-frame中所有的邏輯,以生命周期拉驅(qū)動(dòng)。它們?cè)?code>wxml中對(duì)應(yīng)于每個(gè)標(biāo)簽上的屬性,比如<xr-element transform="position: 1 1 1;" />,就是在xr-element標(biāo)簽上掛在了一個(gè)transform組件。組件的聚合構(gòu)成了后面章節(jié)的元素,也就是wxml中對(duì)應(yīng)的標(biāo)簽。

組件的構(gòu)成主要分為兩部分——數(shù)據(jù)定義和生命周期。

# 讓我們定制一個(gè)組件

通過定制一個(gè)簡(jiǎn)單的組件,我們可以對(duì)組件的機(jī)制有比較清晰的了解:

// 這里只包括類型信息
import XrFrame from 'XrFrame';
// 這里是實(shí)例
const xrFrameSystem = wx.getXrFrameSystem();

// 自定義組件的數(shù)據(jù)接口
export interface IAutoRotateData {
  speed: number[];
}

// 自定義組件的`schema`,詳見后面論述
const AutoRotateSchema: XrFrame.IComponentSchema = {
  speed: {type: 'number-array', defaultValue: [1, 1, 1]}
}

// 定義組件
class AutoRotate extends xrFrameSystem.Component<IAutoRotateData> {
  public readonly schema: XrFrame.IComponentSchema = AutoRotateSchema;

  private _speedX: number = 1;
  private _speedY: number = 1;
  private _speedZ: number = 1;

  // 所掛載的`element`被掛載到場(chǎng)景時(shí)觸發(fā)的回調(diào)。
  public onAdd(parent: XrFrame.Element, data: IAutoRotateData): void {
    this._processData(data);
  }

  // 數(shù)據(jù)更新時(shí)觸發(fā)的回調(diào)。
  public onUpdate(data: IAutoRotateData, preData: IAutoRotateData): void {
    this._processData(data);
  }

  // 渲染每幀觸發(fā)的回調(diào)。
  public onTick(delta: number, data: IAutoRotateData) {
    const trs = this.el.getComponent(xrFrameSystem.Transform);

    // 如果沒有掛載到一個(gè)`Node`節(jié)點(diǎn),則不生效。
    if (!trs) {
      return;
    }

    // 其實(shí)這里實(shí)現(xiàn)有點(diǎn)問題,不過是例子也無傷大雅了(逃
    trs.rotation.x += this._speedX * 0.1;
    trs.rotation.y += this._speedY * 0.1;
    trs.rotation.z += this._speedZ * 0.1;
  }

  // 所掛載的`element`從父節(jié)點(diǎn)`parent`被移除時(shí),或者自己從`element`上唄移除時(shí),觸發(fā)的回調(diào)。
  // 一般用于消除功能的運(yùn)作。
  public onRemove(parent: XrFrame.Element, data: IAutoRotateData): void {

  }

  // 從被掛載的`element`上被移除,或是`element`被銷毀時(shí),觸發(fā)的回調(diào)。
  // 一般用于釋放持有的資源。
  public onRelease(data: IAutoRotateData) {

  }

  private _processData(data: IAutoRotateData) {
    this._speedX = data.speed?.[0] !== undefined ? data.speed[0] : 1;
    this._speedY = data.speed?.[1] !== undefined ? data.speed[1] : 1;
    this._speedZ = data.speed?.[2] !== undefined ? data.speed[2] : 1;
  }
}

// 最后將組件注冊(cè)進(jìn)框架,名為`auto-rotate`
xrFrameSystem.registerComponent('auto-rotate', AutoRotate);

通過以上代碼,我們定制了一個(gè)為掛載的元素提供旋轉(zhuǎn)功能的組件。

首先可以看到的是IAutoRotateDataAutoRotateSchema,接口是為了通過泛型給定義的組件提供類型推斷,而真正作用于運(yùn)行時(shí)邏輯的,則是那個(gè)schema,其類型定義為:

interface IComponentSchema {
  [key: string]: {type: string, defaultValue?: any}
}

schema中,我們定義了組件每個(gè)數(shù)據(jù)的類型type和默認(rèn)值defaultValue。這是由于所有組件在xml中對(duì)應(yīng)的屬性的值都是字符串,所以需要告訴框架如何將這些字符串轉(zhuǎn)換成最終的值,這一部分詳見組件數(shù)據(jù)解析。

在數(shù)據(jù)定義后,我們繼承了xrFrameSystem.Component派生了一個(gè)子類,它有一些生命周期,這就是組件具體邏輯實(shí)現(xiàn)的載體。我們?cè)?code>onAdd和onUpdate的時(shí)候去更新旋轉(zhuǎn)速度數(shù)據(jù),然后在每幀onTick的時(shí)候去修改掛載元素的transform組件中的旋轉(zhuǎn)。注意還有onRemoveonRelease兩個(gè)生命周期,但由于本組件沒有額外資源需要處理,所以不需要執(zhí)行任何操作。

完成了邏輯的實(shí)現(xiàn)后,我們最后一步調(diào)用了xrFrameSystem.registerComponent將這個(gè)組件注冊(cè)到了框架中,并給它了一個(gè)名字auto-rotate,接下來就可以正常使用了。

# 使用這個(gè)組件

使用組件的方式有兩種:

# 在wxml中使用

首先是在wxml中使用,我們只需要按照注冊(cè)的名字和數(shù)據(jù)類型定義將其寫在元素標(biāo)簽上即可:

<xr-node auto-rotate="speed: 2 3 1;" />

如此這個(gè)節(jié)點(diǎn)便會(huì)自動(dòng)旋轉(zhuǎn),速度為{x: 2, y: 3, z: 1}。

組件還可以通過代理的方式來簡(jiǎn)化使用,詳見元素中的數(shù)據(jù)代理部分。

# 手動(dòng)使用

我們也可以在運(yùn)行時(shí)來手動(dòng)添加組件或設(shè)置它的數(shù)據(jù),但注意一定不要和xml中沖突!

要手動(dòng)使用組件,我們需要先拿到元素的實(shí)例引用,詳見場(chǎng)景中獲取元素引用相關(guān)的描述,拿到了引用后便可以執(zhí)行操作:

// 添加組件,并給一個(gè)可選的初始值
el.addComponent(AutoRotate, {speed: [2, 3, 1]});

// 獲取組件并更新數(shù)據(jù),注意`setData`包括`getData`都是通用方法,但有些組件有自己的實(shí)現(xiàn),比如`transform.position`。
el.getComponent(AutoRotate).setData({speed: [1, 1, 1]});

// 手動(dòng)移除組件
el.removeComponent(AutoRotate);