Posted at

今さらだけどCanvasを触ってみた


背景・同期

今さらかもしれませんが、初めてCanvasを使う機会があったため、備忘録も兼ねて投稿します。


Canvasを使ったアニメーション

Webフロントの技術でアニメーションを実現する方法はいくつかありますが、Canvasを使ったアニメーションは無限ループする処理の中で画面を再描画するというものです。


  1. canvas要素からgetContextでコンテキスト情報を取得する。

  2. requestAnimationFrameという関数に自分自身をコールバックとして渡すループ関数を作成する。

  3. ループ関数の最初でコンテキストのclearRectで画面を初期化する。

requestAnimationFrameは古いブラウザでは未対応のものもあるので、対策としてpolyfilを用意すると良いです。

// requestAnimationFrame未対応のブラウザ対策

window.requestAnimFrame = (function() {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
}
);
})();

// Contextを取得
const canvas = document.getElementById('example');
const ctx = canvas.getContext('2d');

// ループ処理
loop();
function loop() {
window.requestAnimFrame(loop);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// ここにアニメーションの処理を書く
}


Canvasへの描画

矩形やパス、画像などを描画するためのメソッドがコンテキストに用意されているので、それを使って画面に描画します。

// 矩形の描画

// fillRect(x, y, width, height)
ctx.fillRect(0, 0, 100, 100);

// パス(円弧)の描画
// arc(x, y, radius, startAngle, endAngle)
ctx.beginPath();
ctx.arc(10, 10, 50, (-90 * Math.PI) / 180, (90 * Math.PI) / 180);
ctx.closePath();
ctx.fill();

// 画像の描画
// drawImage(image, dx, dy, dw, dh)
const img = new Image();
img.src = '/path/to/image.png';
ctx.drawImage(img, 10, 10, img.width, img.height);

アニメーションを実装するには、これらの要素の位置をインクリメントして徐々に移動させます。

let x = 0;

loop();
function loop() {
window.requestAnimFrame(loop);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

// 矩形の移動
x++;
ctx.fillRect(x, 0, 100, 100);
}


Ease-In / Out の実装方法

アニメーションでよく Ease-In / Out を使いますが、Canvasではこれらを自分で実装する必要があります。

function easeIn(p) {

return p * p;
}
function easeOut(p) {
return p * (2 - p);
}

// 変数の初期化
const duration = 100;
const change = 100;
let x = 0, elapsedFrames = 0;
loop();
function loop() {
window.requestAnimFrame(loop);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

// 経過フレーム数を記録する
elapsedFrames++;
if (elapsedFrames > duration) {
elapsedFrames = 0;
}
// 経過フレームの割合からxを計算する
x = change * easeIn(elapsedFrames / duration);
ctx.fillRect(x, 0, 100, 100);
}


まとめ


  • Canvasでは画面を丸ごと再描画することでアニメーションを実現している。

  • getContextで取得したオブジェクトに、画像や矩形を描画するメソッドが用意されている。

  • 描画する位置やサイズを計算してアニメーションを実現する。

  • Ease-In / Out は独自のメソッドで実現できる。