1.

HTML5 Canvas API 入門(描画 / アニメーション / Three.js / PixiJS への発展)

編集
この記事の要点
  • Canvas API は 要素 + JavaScript でブラウザにビットマップ描画する API
  • canvas.getContext("2d") で 2D コンテキスト、"webgl" で 3D(OpenGL ES2 ラッパ)
  • 基本図形: fillRect / strokeRect / arc(円) / beginPath + moveTo + lineTo + stroke(線)
  • 画像・テキスト: drawImage(img, x, y) / fillText(text, x, y)
  • アニメーションは requestAnimationFrame。複雑になったら PixiJS(2D)・Three.js(3D)を使う

Canvas API とは

HTML5 で導入された 要素は、JavaScript からピクセル単位で描画できるビットマップキャンバスです。ゲーム、グラフ、画像処理、データビジュアライゼーションなど幅広く使われます。

最小サンプル: 四角形を描く







width / height は CSS でなく属性で指定するのが鉄則。CSS で指定すると拡大表示になりピクセルがぼやけます。

基本図形の描画

// 直線
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(200, 100);
ctx.lineTo(50, 150);
ctx.closePath();      // パスを閉じる
ctx.stroke();         // 線として描画
// ctx.fill();        // 塗りつぶし

// 円 / 円弧
ctx.beginPath();
ctx.arc(300, 100, 50, 0, Math.PI * 2);  // x, y, r, 開始角, 終了角(ラジアン)
ctx.fillStyle = '#2ecc71';
ctx.fill();

// 半円
ctx.beginPath();
ctx.arc(400, 100, 50, 0, Math.PI);
ctx.stroke();

// 二次ベジェ曲線
ctx.beginPath();
ctx.moveTo(50, 200);
ctx.quadraticCurveTo(150, 100, 250, 200);  // 制御点, 終点
ctx.stroke();

テキスト描画

ctx.font = 'bold 32px sans-serif';
ctx.fillStyle = '#2c3e50';
ctx.textAlign = 'center';        // start | end | left | right | center
ctx.textBaseline = 'middle';     // top | hanging | middle | alphabetic | ideographic | bottom
ctx.fillText('Hello Canvas', 250, 50);

// 枠線のみ
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 2;
ctx.strokeText('Outline', 250, 100);

// 文字幅を測る
const m = ctx.measureText('Hello');
console.log(m.width);  // pixel

画像の描画

const img = new Image();
img.src = '/path/to/photo.jpg';
img.onload = () => {
    // 原寸
    ctx.drawImage(img, 50, 50);

    // サイズ指定
    ctx.drawImage(img, 50, 50, 200, 150);

    // 切り抜き + 配置(sx, sy, sw, sh, dx, dy, dw, dh)
    ctx.drawImage(img, 0, 0, 100, 100, 300, 50, 200, 200);
};

変形(回転・拡大・移動)

ctx.save();                          // 状態を保存
ctx.translate(250, 150);             // 原点を移動
ctx.rotate(Math.PI / 4);             // 45 度回転
ctx.scale(1.5, 1.5);                 // 1.5 倍拡大
ctx.fillStyle = '#9b59b6';
ctx.fillRect(-50, -25, 100, 50);     // 移動後の原点が中心
ctx.restore();                       // 元の状態に戻す

アニメーション: requestAnimationFrame

毎フレーム描き直すには requestAnimationFrame を使います。setInterval ではブラウザの再描画タイミングと同期しないのでカクつきます。

let x = 0;
let vx = 2;

function tick() {
    // 1. 画面クリア
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // 2. 状態更新
    x += vx;
    if (x > canvas.width - 50 || x < 0) vx = -vx;

    // 3. 描画
    ctx.fillStyle = '#3498db';
    ctx.fillRect(x, 100, 50, 50);

    // 4. 次フレームを予約
    requestAnimationFrame(tick);
}

tick();

マウス入力でお絵描き

let drawing = false;
canvas.addEventListener('mousedown', e => {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX, e.offsetY);
});
canvas.addEventListener('mousemove', e => {
    if (!drawing) return;
    ctx.lineTo(e.offsetX, e.offsetY);
    ctx.stroke();
});
canvas.addEventListener('mouseup', () => drawing = false);

Canvas API でできることの限界

用途素の Canvas推奨ライブラリ
簡単な図形・グラフOKChart.js
2D ゲーム(スプライト多数)遅いPixiJS(WebGL 加速)
3D 描画不可(getContext("webgl") 必要)Three.js / Babylon.js
SVG 的なベクタパスは描けるが座標管理が大変SVG + D3.js
動画フィルタgetImageData / putImageData で可能WebGL + シェーダ

WebGL コンテキストへの拡張

// 2D → 3D の入り口
const gl = canvas.getContext('webgl2');
if (!gl) {
    alert('WebGL2 がサポートされていません');
}

// 実際は Three.js を使うのが現実的
// npm install three
import * as THREE from 'three';
const scene  = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ canvas });
const cube = new THREE.Mesh(
    new THREE.BoxGeometry(),
    new THREE.MeshNormalMaterial()
);
scene.add(cube);
camera.position.z = 3;

renderer.setAnimationLoop(() => {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
});

FAQ

Q: Canvas で描いた絵を画像保存したい
A: canvas.toDataURL('image/png') で base64 取得、canvas.toBlob(cb) で Blob 取得が可能です。

Q: 高 DPI(Retina)でぼやける
A: canvas.width = w * devicePixelRatio にして ctx.scale(devicePixelRatio, devicePixelRatio)、CSS 側は w px に。

Q: SVG とどちらが良い?
A: 拡大に強く要素単位でイベント取りたいなら SVG、ピクセル制御や多数オブジェクトのアニメは Canvas が高速です。

編集
Post Share
子ページ
  1. 図形
  2. 直線・曲線(パスでの描画)
同階層のページ
  1. Canvas API
  2. Drag and Drop API
  3. History API
  4. WebStorage API
  5. File API
  6. System Information API