JavaScriptでMLTをgifっぽく表示してみる

2018年のアドベントカレンダーは終わってしまったが埋めネタを書かねばならぬ...！
この記事ではJavaScriptでMLTをgifっぽく表示するページを作ったのでその方法の紹介です。

![output.gif](https://qiita-image-store.s3.amazonaws.com/0/165335/ab36bd77-9c75-5236-e5bf-c04ae6e84ba5.gif)

MLTって何という方はこちらの記事を参照。
[GolangでMLTを画像に変換する](https://qiita.com/xiaca/items/c9b949d8950c233022da)

完成したサイトはこちら。
https://b.aahub.org/player-converter

実装しなきゃいけないのは以下のとおりです。

1. MLTを分割
2. 配列に入ったテキストを順番に表示

ちょっとプログラミングの心得がある方なら瞬間で実装が思いつくんじゃないかと思いますが、記事にしておきます。

あと、毎度のことながらStenciljsを使ってます。だって使いやすいんだもの。
[Stencil](https://stenciljs.com/docs/getting-started/)

## ソースコード
[GitHub](https://github.com/AAHub/mlt-player)
GitHubにソースコードあげてあります。

## 1. MLTを分割
MLTが何かというとざっくりAAを[SPLIT]という文字で区切ったものです。それ以外は普通のテキストと変わりません。

```text
　　　(~)
　γ´⌒｀ヽ
　 {i:i:i:i:i:i:i:i:}　　 このセーター
　（　´・ω・）　　しまむらで買ったんだ。
　 （:::::::::：:::）
　　 し─Ｊ
[SPLIT]
　　　(~)
　γ´⌒｀ヽ
　 {i:i:i:i:i:i:i:i:}
　（・ω・｀　）　　左向き
　 （:::：:::::::::）
　　 し─Ｊ
[SPLIT]
```

ということで、MLを分割する方法はJavaScriptならsplitを使えばよいだけです。簡単ですね。

```javascript
let mlt = text.split("[SPLIT]");
```

というわけで残りのcomponents部分も書いてみます。作るのはtextareaに入力したMLTを分割して次のPlayerPageに渡すページです。

```typescript:src/components/aa-player-converter/aa-player-converter.tsx
import { Component, Element, State } from "@stencil/core";

@Component({
  tag: "aa-player-converter",
  styleUrl: "aa-player-converter.css"
})
export class PlayerConverterPage {
  @State() src: string = "";

  @Element() el: HTMLElement;

  textInput(el) {
    this.src = el.srcElement.value;
  }

  async convert() {
    const mlt = this.src.split("[SPLIT]");
    (this.el.closest("ion-nav") as any).push("aa-player", { mlt: mlt });
  }

  render() {
    return [
      <ion-header>
        <ion-toolbar>
          <ion-title>コンバーター</ion-title>
        </ion-toolbar>
      </ion-header>,
      <ion-content>
        <div class="input-aa-wrapper">
          <textarea
            id="aa-textarea"
            class="input-aa"
            placeholder="MLTを入力"
            onInput={e => this.textInput(e)}
          />
        </div>
        <div class="convert-button-wrapper">
          <ion-button class="u-mt16" onClick={() => this.convert()}>
            コンバート
          </ion-button>
        </div>
        <div class="is-center footer u-mt40 u-mb20">
          <nav-footer />
        </div>
      </ion-content>
    ];
  }
}
```

上記でコードで以下の画面が生成されます。
<img width="826" alt="Screen Shot 2018-12-31 at 2.43.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/bc3aad27-db6f-6892-4c07-8711e596266f.png">


## 2. 配列に入ったテキストを順番に表示
さて、前項でMLT形式のテキストを分割して文字列配列にすることはできました。残りは、その文字列を順番の表示することです。これはJavaScriptのSetIntervalを使えばできます。SetIntervalでindexをカウントしていけばOKです。

```html
 <!-- this.mltが前項で分割した文字列配列 -->
 <div class="preview-wrapper">{this.mlt[this.idx]}</div>
```


```javascript
    // idxが端まできたら最初に戻す
    setInterval(async () => {
      if (this.idx + 1 < this.mlt.length) {
        this.idx = this.idx + 1;
      } else {
        this.idx = 0;
      }
    }, 100);
```

上記の処理を行えば、配列の中のAAを順番に表示することができます。

```typescript:src/components/aa-player/aa-player.tsx
import { Component, State, Prop } from "@stencil/core";

@Component({
  tag: "aa-player",
  styleUrl: "aa-player.css"
})
export class PlayerPage {
  @Prop() mlt: string[] = [];
  @State() idx: number = 0;
  isPlay: boolean = false;
  playingId: any;

  play() {
    if (this.isPlay) {
      return;
    }
    this.isPlay = true;
    this.playingId = setInterval(async () => {
      if (this.idx + 1 < this.mlt.length) {
        this.idx = this.idx + 1;
      } else {
        this.idx = 0;
      }
    }, 100);
  }

  refresh() {
    this.idx = 0;
    this.isPlay = false;
    clearInterval(this.playingId);
  }

  pause() {
    this.isPlay = false;
    clearInterval(this.playingId);
  }


  render() {
    return [
      <ion-header>
        <ion-toolbar>
          <ion-title>プレイヤー</ion-title>
        </ion-toolbar>
      </ion-header>,
      <ion-content>
        <div class="mlt-preview-wrapper">
          <div class="controller-wrapper">
            <ion-button
              color="dark"
              size="small"
              fill="clear"
              onClick={() => this.refresh()}
            >
              <ion-icon slot="icon-only" name="skip-backward"></ion-icon>
            </ion-button>
            <ion-button
              color="dark"
              size="small"
              fill="clear"
              onClick={() => this.play()}
            >
              <ion-icon slot="icon-only" name="play" />
            </ion-button>
            <ion-button
              color="dark"
              size="small"
              fill="clear"
              onClick={() => this.pause()}
            >
              <ion-icon slot="icon-only" name="pause" />
            </ion-button>
            <div class="index">
              {this.idx + 1}/{this.mlt.length}
            </div>
          </div>
          <div class="preview-wrapper">{this.mlt[this.idx]}</div>
        </div>
        <div class="is-center footer u-mt40 u-mb20">
          <nav-footer />
        </div>
      </ion-content>
    ];
  }
}
``` 

これで、以下のような画面になり、再生ボタンを押すと配列の中のAAを順番に表示するようになります。
<img width="749" alt="Screen Shot 2018-12-31 at 2.53.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/165335/6248f6b4-e817-14bb-09c6-273046596cfd.png">


## まとめ
以上、MLTをgifっぽく表示する内容でした。
興味持った方は下にあるソースコードをぜひ動かしてみてください。
[GitHub](https://github.com/AAHub/mlt-player)
それでは、