MathBox でスライドを作る

　今回はスライドを作ってみます。 MathBox は一般的なプレゼンテーションソフトのように「スライドの中にグラフィックスを埋め込む」のではなく、「グラフィックスの中にスライドを埋め込む」という発想のようですので、それを意識すると理解しやすいかもしれません。

# 基本のコード
　[前回](https://qiita.com/YuichiSato/items/a1a3cfd7b0057f7d68fd)のコードにプレゼンテーションスライドを作成するコードとスライドのページ送りするためのコードを追加しました。

　プレゼンテーションスライドを作成するコードは以下の部分です。また、これ以降で `view` と書かれていた部分は `present` に置換します。

```javascript
present = view.present({
  index: 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>
	<div style="position: absolute;
		    left: 50%;
		    bottom: 21px;">
	    <span onclick="prevSlide()" style="display: inline-block;
			   height: 34px;
			   width: 55px;
			   background-color: ghostwhite;
			   text-align: center;
			   vertical-align: middle;
			   border: solid 2px black;
			   border-radius: 8px;">Prev</span>
	    <span onclick="nextSlide()" style="display: inline-block;
			   height: 34px;
			   width: 55px;
			   background-color: ghostwhite;
			   text-align: center;
			   vertical-align: middle;
			   border: solid 2px black;
			   border-radius: 8px;">Next</span>
	</div>
	<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],
	 });

	 present = view.present({
	     index: 1
	 })

	 function prevSlide () {
	     present.set('index', present.get('index') - 1);
	 }

	 function nextSlide () {
	     present.set('index', present.get('index') + 1);
	 }

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

	 present.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,
	 });

	 present.grid({
	     stroke: 'dashed',
	 });
	</script>
    </body>
</html>
```
# スライドを埋め込む
　直線と Sin カーブそれぞれにスライドを埋め込んでみます。それぞれ `present.slide()` として続けるとスライドを埋め込む事ができます。以下のように変更すると、ページ間を行き来できるようになります。

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

present.slide().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,
});
```

## メソッドチェーンでまとめる
　このコードをメソッドチェーンを使うと、直線と Sin のコードブロックを繋げて次のように書けます。直線のブロックの最後に `.end()` を置いて `.slide()` と続けます。 `end()` はメソッドチェーンをして生じた要素の親子関係を切るために使います。ドキュメントから引用すると `group().child().child().end().sibling();` となります。
　ちなみに二枚目のスライドに対応する `end()` が入っていませんが、無くても不都合がないため省略しています。

```javascript
present.slide().interval({
  width: 2,
  expr: function (emit, x, i, time) {
    emit(x, 0);
  },
  items: 1,
  channels: 2,
}).line({
  color: 0x3090FF,
  width: 10,
}).end()
  .slide().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,
  });
```

## 重ねて描画したい場合
　上記のコードだと、直線が描画されなくなって、Sin カーブの描画がされます。一方で `.end()` を削除してみると、直線の描画を続けたまま Sin カーブも描画されるようになります。Sin カーブが直線の子要素になったという事が分かります。
　このように次々と重ねて描画したい場合は、 `.end()` を入れずに親子関係を維持したまま続ければ実現できます。

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

```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>
	<div style="position: absolute;
		    left: 50%;
		    bottom: 21px;">
	    <span onclick="prevSlide()" style="display: inline-block;
			   height: 34px;
			   width: 55px;
			   background-color: ghostwhite;
			   text-align: center;
			   vertical-align: middle;
			   border: solid 2px black;
			   border-radius: 8px;">Prev</span>
	    <span onclick="nextSlide()" style="display: inline-block;
			   height: 34px;
			   width: 55px;
			   background-color: ghostwhite;
			   text-align: center;
			   vertical-align: middle;
			   border: solid 2px black;
			   border-radius: 8px;">Next</span>
	</div>
	<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],
	 });

	 present = view.present({
	     index: 1
	 })

	 function prevSlide () {
	     present.set('index', present.get('index') - 1);
	 }

	 function nextSlide () {
	     present.set('index', present.get('index') + 1);
	 }

	 present.slide().interval({
	     width: 2,
	     expr: function (emit, x, i, time) {
		 emit(x, 0);
	     },
	     items: 1,
	     channels: 2,
	 }).line({
	     color: 0x3090FF,
	     width: 10,
	 }).end()
		.slide().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,
		});

	 present.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="Yoerxz" 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="slide">
  <span>See the Pen <a href="https://codepen.io/satoyuichi/pen/Yoerxz/">
  slide</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>