MathBox を使ってみる

# MathBox
　以前から気になっていた "MathBox" を使ってみました。[Making WebGL Dance](https://acko.net/files/fullfrontal/fullfrontal/webglmath/online.html)で使われていると言われればどんなことが出来るか分かるかと思います。[公式サイト](https://acko.net/blog/mathbox2/) には "PowerPoint Must Die" と過激な事が書いてある通り、スライドを作ることもできます。

　いくつかの記事に分けて使い方を書いていこうと思います。

- [MathBox でスライドを作る](https://qiita.com/YuichiSato/items/4e1c8ab95b62f1811860)
- [MathBox でトランジションアニメーション（フェードイン/フェードアウト）を作る](https://qiita.com/YuichiSato/items/993f80aa07c12dee6785)

# 自分にとっての魅力
- ベクトル、曲線や曲面など大抵は描画出来る
- スライド間の遷移やグラフのアニメーションが可能
- JavaScript である（ので、その他 JavaScript で出来ることはなんでも出来る）
 - TeX 記法で式がかける(KaTeX)
 - 3D モデルの描画が出来る(Three.js)

といったところが魅力的でした。

# 使い方
　使い方は GitHub の [README](https://github.com/unconed/mathbox) や [公式サイト](https://acko.net/blog/mathbox2/) を見ればなんとなく分かるのですが、自分で思い描いているものを書こうとすると骨が折れました。どちらかというとコードが書けた後にドキュメントを読み返すと「あぁ、こういうことが言いたかったのね」となる感じでした。

　まずは直線と Sin カーブを描画するサンプル `examples/test/xyzw.html` を基にして見ていきましょう。コードは以下の通りです。

```html:examples/test/xyzw.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>MathBox - XYZW Test</title>
  <script src="../../build/mathbox-bundle.js"></script>
  <link rel="stylesheet" href="../../build/mathbox.css">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1">
</head>
<body>
  <script>
    mathbox = mathBox({
      plugins: ['core', 'controls', 'cursor'],
      controls: {
        klass: THREE.OrbitControls
      },
    });
    three = mathbox.three;

    three.camera.position.set(2.3, 1, 2);
    three.renderer.setClearColor(new THREE.Color(0xFFFFFF), 1.0);

    view = mathbox.cartesian({
      range: [[-6, 6], [-1, 1], [-1, 1]],
      scale: [6, 1, 1],
    });

    view.interval({
      width: 128,
      expr: function (emit, x, i, time) {
        var d = Math.sin((x + time) * 2);

        emit(x, 0);
        emit(x, d * .5);
      },
      items: 2,
      channels: 2,
    });
    view.line({
      color: 0x3090FF,
      width: 10,
    });

  </script>
</body>
</html>
```

こちらをブラウザで開くと時間的に変化する水色の直線とサインカーブが描かれ、Three.js の OrbitControls と同じ操作で視点移動が可能です。こちらを少しずつ変更していってみます。

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="result" data-user="satoyuichi" data-slug-hash="LKQzZa" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="xyzw">
  <span>See the Pen <a href="https://codepen.io/satoyuichi/pen/LKQzZa/">
  xyzw</a> by Yuichi Sato (<a href="https://codepen.io/satoyuichi">@satoyuichi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## メソッドチェーン
　`view.interval(...)` の部分は以下のように書くことも可能です。サンプルでもこのように書かれていることが多いです。

```javascript
view.interval({
  width: 128,
  expr: function (emit, x, i, time) {
    var d = Math.sin((x + time) * 2);

    emit(x, 0);
    emit(x, d * .5);
  },
  items: 2,
  channels: 2,
}).line({
  color: 0x3090FF,
  width: 10,
});
```

## 描画色を変える
　直線と Sin カーブで色を変えてみます。先ほどまでは同じ `view.interval(...)` 内で書いていたのですが、それぞれ分けて描画します。
　直線のプロパティの `width` は配列の幅を表しているのですが、直線なので始点と終点だけあれば良いため `2` に変更しました。また `items` は先ほどの直線と Sin カーブの二種だったのが、直線一種のみになったので `1` としています。 Sin カーブの `items` も同じく `1` となります。

```javascript
// 直線
view.interval({
  width: 2,
  expr: function (emit, x, i, time) {
    emit(x, 0);
  },
  items: 1,
  channels: 2,
}).line({
  color: 0x3090FF,
  width: 10,
});

// Sin カーブ
view.interval({
  width: 128,
  expr: function (emit, x, i, time) {
    var d = Math.sin((x + time) * 2);
    emit(x, d * .5);
  },
  items: 1,
  channels: 2,
}).line({
  color: 0xFF3090,
  width: 10,
});
```

## グリッド
　このままでは位置が分かりにくいので、グリッドを追加します。下記のコードを追加します。

```javascript
view.grid({
  stroke: 'dashed',
});
```

　`stroke` に `'dashed'` を指定しているので、ダッシュ線でグリッドが表示されます。座標軸が伸びて見えますが正常です。ドキュメントを見ながら、下記の箇所を変更しながら観察してみてください。

```javascript
view = mathbox.cartesian({
  range: [[-6, 6], [-1, 1], [-1, 1]],
  scale: [6, 1, 1],
});
```

# コード全体
　ここまでのコード全体は下記の通りです。

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>MathBox - XYZW Test</title>
  <script src="../../build/mathbox-bundle.js"></script>
  <link rel="stylesheet" href="../../build/mathbox.css">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1">
</head>
<body>
    <script>
     mathbox = mathBox({
	 plugins: ['core', 'controls', 'cursor'],
	 controls: {
             klass: THREE.OrbitControls
	 },
     });
     three = mathbox.three;

     three.camera.position.set(2.3, 1, 2);
     three.renderer.setClearColor(new THREE.Color(0xFFFFFF), 1.0);

     view = mathbox.cartesian({
	 range: [[-6, 6], [-1, 1], [-1, 1]],
	 scale: [6, 1, 1],
     });

     view.interval({
	 width: 2,
	 expr: function (emit, x, i, time) {
             emit(x, 0);
	 },
	 items: 1,
	 channels: 2,
     }).line({
	 color: 0x3090FF,
	 width: 10,
     });

     view.interval({
	 width: 128,
	 expr: function (emit, x, i, time) {
             var d = Math.sin((x + time) * 2);
             emit(x, d * .5);
	 },
	 items: 1,
	 channels: 2,
     }).line({
	 color: 0xFF3090,
	 width: 10,
     });

     view.grid({
	 stroke: 'dashed',
     });
    </script>
</body>
</html>
```

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="result" data-user="satoyuichi" data-slug-hash="xoYXRQ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="xyzw color changed">
  <span>See the Pen <a href="https://codepen.io/satoyuichi/pen/xoYXRQ/">
  xyzw color changed</a> by Yuichi Sato (<a href="https://codepen.io/satoyuichi">@satoyuichi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>