Canvasのことをちょっぴり知る

## この記事について
HTMLのCanvasで「どんなことができるのか？」「どんな作品ができるのか」というところを重点的にまとめた記事になります。技術的な内容にはあまり触れていないです。

## 対象者
- Canvasを知らない人や触ったことがない人

### Canvasとは？
HTML5から導入された図形を描くための技術仕様です。
JavascriptとHTMLの`<canvas>`を使用して図形を描くことができます。

Canvasを使った作品例だと以下のようなものがあります。

- [ホムンクルス](https://homunculus.jp/)のコーポレートサイト
- [ぷるぷるスパークリングゼリー](http://www.hakutsuru.co.jp/purupuru/)の商品紹介のサイト
- [雲の上を飛んでるような作品](https://mrdoob.com/#/131/clouds)
- [トランプがひたすら落ちてくる作品](https://mrdoob.com/#/142/winning_solitaire)

### できること
基本的に2Dの図形を対象としていますが、3Dの図形も描けるので、アイディア次第では様々なことが表現できそうです:clap_tone1:
3Dの図形を描くときは [Canvas API](https://developer.mozilla.org/ja/docs/Web/API/Canvas_API)ではなく[WebGL API](https://developer.mozilla.org/ja/docs/Web/API/WebGL_API)を使用して描きます。

2Dでできることは以下です。

- 円や四角などの色々な形の図形の作成
- それらを変形させる
- グラデーションをつける
- 画像との合成やクリッピング
- アニメーションをつける（CSSのアニメーションではなくCanvasAPIで用意されてるアニメーション）

### 基本的な描画の流れ
1. HTMLで`<canvas>`要素のwidthとheightとidを指定する
2. getElementByIdメソッドで要素を取得して、getContextメソッドの引数に`2D`を渡すと2Dの図形を描画するのに必要なメソッドやプロパティを持つオブジェクトが取得できます
3. canvasAPIの機能を使用して図形を描く

- widthとheightを指定しないとデフォルトで`width:300px`の`height:150px`として設定されます。この枠の中がキャンバスとなって図形を描くスペースとなります。
- 引数に `webgl`を渡すと3Dの図形を描画できるオブジェクトが取得できます。

```html:index.html
<canvas id="canvas"></canvas>
```
```javascript:main.js
// DOMの中からcanvas要素を取得
const canvas = document.getElementById('canvas');
// 2Dの図形を描画するメソッドやプロパティを持ったオブジェクトを取得
const ctx = canvas.getContext('2d');
// 色を緑色に指定
ctx.fillStyle = 'green';
// 四角を描画(x, y, 幅, 縦)
ctx.fillRect(10, 10, 150, 100);
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="kena-nk" data-slug-hash="eYdawGg" 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="eYdawGg">
  <span>See the Pen <a href="https://codepen.io/kena-nk/pen/eYdawGg">
  eYdawGg</a> by kena-nk (<a href="https://codepen.io/kena-nk">@kena-nk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### Canvasの基本的なアニメーション
CSSのアニメーション（`@keyframes`とか）とはちょっと異なります。
Canvasでのアニメーションは以下のように描画されます。

1. 要素を削除
2. 要素を描画
3. 要素を動かす
4. 終了でなければ1.に戻る

イメージとしてはパラパラ漫画のように画面が挿し変わっていく感じです。

再描画を行うループメソッドは以下3つを状況に応じて使い分けるみたいです↓

- setInterval()：一定時間ごとに特定の処理を繰り返す
- setTimeout()：一定時間後に特定の処理をおこなう
- requestAnimationFrame()：ブラウザ描画単位で呼びだされて、次の描画がされる前にアニメーションを実行する関数を呼び出す

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="kena-nk" data-slug-hash="mdrZbQX" 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="mdrZbQX">
  <span>See the Pen <a href="https://codepen.io/kena-nk/pen/mdrZbQX">
  mdrZbQX</a> by kena-nk (<a href="https://codepen.io/kena-nk">@kena-nk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### 試しに作った作品
- カーブを描く直線が描けるプロパティで作ったプリン
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="html,result" data-user="kena-nk" data-slug-hash="OJRYYBw" 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="OJRYYBw">
  <span>See the Pen <a href="https://codepen.io/kena-nk/pen/OJRYYBw">
  OJRYYBw</a> by kena-nk (<a href="https://codepen.io/kena-nk">@kena-nk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- 円と直線を組み合わせて作ったドラえもん
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="kena-nk" data-slug-hash="WNGBBYP" 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="WNGBBYP">
  <span>See the Pen <a href="https://codepen.io/kena-nk/pen/WNGBBYP">
  WNGBBYP</a> by kena-nk (<a href="https://codepen.io/kena-nk">@kena-nk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## おわりに
Canvasを初めて触ってみたの感想としては、アニメーション付けなければお絵かきしているような感覚で使えて楽しいな〜と思いました:raised_hands_tone1:

でも、ただ普通の丸を描くだけでも、x座標やy座標の指定だったり、Mathオブジェクトが頻繁に登場したりで数学が苦手な私的には辛みを感じたのですが。。。図形が完成していく過程は面白かったです！

今回は触っていないのですが、調べてみるとライブラリも充実していました！
実務で使うとしたらやはりライブラリを使用するんですかね？

以下MDNがまとめてくれているライブラリ一覧です🔽
https://developer.mozilla.org/ja/docs/Web/API/Canvas_API#libraries

興味がある方はぜひ[Canvasチュートリアル](https://developer.mozilla.org/ja/docs/Web/API/Canvas_API/Tutorial)やってみてください！！では！！

## おまけ
### CanvasがHTML5に導入された経緯
> Mac OS X v10.4の内部でWebKitコンポーネントとして、DashboardウィジェットやSafariでのアプリケーションを強化するために、2004年にアップルが最初に導入した。後に、Mozilla FirefoxやOperaでも採用され、WHATWGで、新しい標準規格として標準化された。

> 2009年の夏頃に、文字列描画のAPIとピクセル操作のAPIが追加になり、ウェブブラウザに実装された。

> その後、HTML Canvas 2D Context, Level 2 が作られ、2012年12月17日に最初の W3C Working Draft が発表になった。

>ソース：[Wikipedia](https://ja.wikipedia.org/wiki/Canvas%E8%A6%81%E7%B4%A0)

要約すると、Appleが最初にDashboardウィジェットやSafariを良くしたくて取り入れたら、その良さに気づいた他のみんなも導入し始めて、最終的にHTML5入れちゃうか！って感じで追加されたのかなと思う


#### WHATWG(ワットダブルジー)とは？
HTMLと関連技術の開発をするためのコミュニティです！
元々はWeb技術の標準化を行う、[World Wide Web](https://ja.wikipedia.org/wiki/World_Wide_Web)(略称:W3C)の対抗組織だったみたいです。

HTML5の策定にあたってW3CとWHATWGは協力関係となり、WHATWGが提唱したものを元にW3Cが策定しました。
2019年からはWHATWGが随時更新していく「[HTML Living Standard](https://html.spec.whatwg.org/multipage/)」をHTML標準と認め、W3Cが独自に規格を策定しないことなどが合意されました。

MDNが公式ドキュメントだと思ってたけどHTML Living Standardが公式ドキュメントみたいです。

## 参考サイト
Canvasアニメーションの要点
https://qiita.com/nekoneko-wanwan/items/33afa5d20264c83b2bd1

Canvasのイベント操作まとめ
https://qiita.com/nekoneko-wanwan/items/9af7fb34d0fb7f9fc870

Canvasチュートリアル
https://developer.mozilla.org/ja/docs/Web/API/Canvas_API/Tutorial