Canvas APIで「ポケモン」を描いてみる

### Canvas API 
HTMLのCanvasタグを用いて、Javascriptでお絵かきができます。
https://developer.mozilla.org/ja/docs/Web/API/Canvas_API

canvasのDOM要素に対して、色を足したり、線を足すことで、絵として表現できます。


```html
<canvas id="canvas"></canvas>
```
単純な四角形を描画するだけであれば、mozillaの公式に紹介があるのですが、
もう少し込み入った、やや複雑な絵を描きたいと思ったときに、サンプルがまだまだ少ない感じました。
この記事がその一つになれれば幸いです。


### Canvas で絵を描く
実際にポケモンのコダックをCanvas APIを使って描いてみました。
今回はReact上で表現しています。
![スクリーンショット 2021-12-04 18.26.52.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435918/70f36d15-221e-d2b4-25dd-5b66613ada9a.jpeg)




#### Canvas描画用のコンポーネントを用意する

```javascript
export const Canvas: React.FC = () => {

  useEffect(() => {
    const canvas = document.getElementById("canvas") as HTMLCanvasElement
    const context = canvas.getContext("2d") as CanvasRenderingContext2D
    kDuck(context)  // Canvasの具体的な描画内容を表現したメソッド
  }, []);

  return (
    <div>
      <canvas width={800} height={680} id={"canvas"} />
    </div>
  )
}
```

ポケモンのコダックを描画するための `KDuck`メソッドの中身はこんな感じです。

```javascript
export const kDuck = (context: CanvasRenderingContext2D) => {
  comb(context, "#383838") // トサカ
  rightArm(context, "#F2C86B"); // 右腕
  head(context, "#F2C86B") // 頭
  eyes(context, "#eeeeee") // 両目
  tail(context, "#F2C86B") // 尻尾
  rightFoot(context, "#C4C2BB") // 右足
  bodyAndLeftArm(context, "#F2C86B") // 胴体と左腕
  beak(context, "#C4C2BB") // くちばし
  leftFoot(context, "#C4C2BB") // 左足
}
```

① canvasタグを内包したコンポーネントを用意し、
② useEffectを用いて初回レンダリング時に、描画したいものを表現したメソッド`kDuck(context)`を実行しています。
③ `kDuck`メソッドの実体はコダックの身体の各パーツを束ねたものになっており、DOMから取得したcanvasの`context`とそのパーツに必要な色を引数に受け取っています。



### KDuckの具体的な描画について
1つ試しに`トサカ`パーツである、`comb(coontext, "#383838")`の実体をご紹介します。

```typescript
// トサカ
const comb = (context: CanvasRenderingContext2D, fillColor: string) => {
  context.beginPath()
  context.strokeStyle = "#383838"
  context.fillStyle = fillColor
  context.moveTo(376, 90) // 始点
  context.quadraticCurveTo(365, 103, 395, 145)
  context.quadraticCurveTo(408, 146, 417, 149)
  context.quadraticCurveTo(478, 132, 476, 130)
  context.quadraticCurveTo(482, 117, 470, 112)
  context.quadraticCurveTo(424, 128, 415, 142)
  context.quadraticCurveTo(434, 110, 444, 82)
  context.quadraticCurveTo(443, 76, 428, 74)
  context.quadraticCurveTo(408, 105, 404, 138)
  context.quadraticCurveTo(393, 94, 387, 85)
  context.quadraticCurveTo(376, 90, 376, 90) // 終点
  context.fill()
  context.stroke()
  context.closePath()
}
```
左上を起点とする、xとyの座標で描画位置を指定しています。
以下で紹介する `moveTo(x,y)` や `quadraticCurveTo(x1,y1,x2,y2)` に座標を入力することで、線を描画しています。
① まず `beginPath()` で描画を開始します。
　https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/beginPath
② `strokeStyle`　で描画したい線そのものの色を指定します。
③　`fillStyle` で描画したい内容の色を指定します。
④ `moveTo()`で描画を開始しています。
　https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/moveTo
⑤ `quadraticCurveTo()`で曲線を表現しています。
 　https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo
　今回は用いてませんが、直線を描画する`lineTo()`メソッドもあります。　　
　 https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/lineTo
⑥ `fill()`で、描画したものをfillStyleで指定した色に塗りつぶします。
⑦ `stroke()`で、描画の線が実際に生成されます。
(⑧ コダックの他のパーツ描画に影響が出ないよう、 `closePath()` を挟んでいます。)

トサカ部分の描画は以上です。このような実装を、コダックのパーツごとに実装していくことで、冒頭の画像のようなコダックを描画できます。

### おわりに
ここまで、Canvas APIを用いた、やや複雑な描画の仕方を、　コダックを題材に取り上げてみました。
ですが、(x,y)座標によって実現していることを踏まえると、目視でその位置を決めていくことは現実的でないと思います。
Canvas APIでやや複雑な描画をしようと思ったときに、こんなものを使えば良いのでは、というアイデアがあるので、別の機会に投稿できればと思います。 

Reactなどを用いて、「状態」に応じて色を変更するとか、描画する内容を変更する、といったことも可能です。