Tutorial: テキストレイアウトの拡張

テキストレイアウトの拡張

MessageLayerにある文字のレイアウトは複数のTextCustomizerによって計算されます。

レイアウトは以下の手順で行われます

  1. TextCustomizerのインスタンスを作る、TextPropertiesの配列を渡します
  2. 全てのTextCustomizerをループし
    1. timePassed 属性に過ぎた時間を格納する
    2. perform()を実行する
    3. このTextCustomizerは終わったかどうかをisEnded 属性で判断する
    4. 全てのTextCustomizerが終わった場合、文字表示は終了とする
    5. 一つでも終わってない場合は、次のアニメーションフレームでループを続く

レイアウトをいじりたい場合はTextCustomizerのサブクラスを作って、perform()の上書きすべきです。

このメソッドの中では、textPropertiesを自由にいじられます。textPropertiesの数は変えられないですが(削除と追加は対応してないです)、個別のTextPropertiesの属性などは自由にいじってもいいです。例えば文字を動かしたい場合はtext.rect.xtext.rect.yに新しい値を入れればいいです。

注意点:

  • 時間に基づいた計算はtimePassed属性で計算してください。メッセージレイヤーは自動的に適切な値を格納します。
  • perform()の外でTextPropertiesを変わらないとでください、例えばsetTimeout経由とか。

これは全ての文字を10px下にずらすTextCustomizerです。

class MoveDown extends TextCustomizer {
  constructor(messageLayer, oldTexts, newTexts) {
    super(textLayer, oldTexts, newTexts);
    this.newTexts = newTexts;
  }
  perform() {
    this.newTexts.forEach(text => {
      text.rect.y += 10;
    });
  }
}

TextCustomizerを適用する

TextCustomizerをメッセージレイヤに適用させるには以下の手順を踏まえてください。まずはTextCustomizerを登録するします。

// plugin/movedown.js
MessageLayer.textCustomizers.moveDown10px = MoveDown;

次は、個別のmessage layerでTextCustomizerを有効にします。

layer.textCustomizers.push('moveDown10px');

同じ感じでTextCustomizerを無効化もできます。

let index = layer.textCustomizers.indexOf('moveDown10px');
layer.textCustomizers.splice(index, 1);

気をづけるべきところは、TextCustomizerをMessageLayer.textCustomizersに追加する時、TextCustomizerは「正しいところに追加する」責任を持ってます。例えばbaseTextCustomizerの前にTextCustomizerを追加すべきではない、複数のTextCustomizerがある場合も同じです、他のプラグインと衝突しないように気をつけてください。

これはTextCustomizerをmessage layerに適用させるプラグインのサンプルです。

// plugin/movedown.js
Tag.actions.toggle_move_down = new TagAction({
  rules: {
    layer  : {type: "MESSAGE_LAYER", required: true},
    page   : {type: /fore|back/, required: true}
  },
  action: (args)=> {
    const layer = args.layer[args.page];
    let index = layer.textCustomizers.indexOf('moveDown10px');
    if (index >= 0) {
      layer.textCustomizers.splice(index, 1);
    } else {
      layer.textCustomizers.push('moveDown10px');
    }
    return 0;
  }
});
// first.ks
[o2_loadplugin module="movedown.js"]
before
[toggle_move_down]
after

アニメーション

デフォルトでは、message layerはできるだけ低いFPSで描画します([delay]タグでFPSを指定できます)。TextCustomizerでアニメーションをしたい場合はこうしてください:

  • isAnimation属性をtrueにする、これでFPSはできるだけ高めます。
  • isEnded属性を実装する。アニメーションが終わったかどうかをmessage layerに教える属性です。全てのTextCustomizerが終わってから文字表示は終わります。だからisEndedtrueの場合でもperform()が実行される場合はあります、注意してください。

文字を1秒つづ表示するTextCustomizerのサンプルです:

class OneByOne extends TextCustomizer {
  constructor(messageLayer, oldTexts, newTexts) {
    super(textLayer, oldTexts, newTexts);
    this.newTexts = newTexts;
  }
  perform() {
    this.newTexts.forEach((text, i)=> {
      if (this.timePassed / 1000 > i) {
        text.styles.visible = true;
      } else {
        text.styles.visible = false;
      }
    });
  }
  get isEnded() {
    return this.timePassed / 1000 >= this.newTexts.length;
  }
  get isAnimation() {
    return true;
  }
}