canvas に次々に drawImage() するときの覚え書き
例えば連番の画像 0.png〜100.png があったとしてそれを次々に drawImage() でcanvasに描きこみたい。
canvas 要素には width, height 属性を必ず書く
そうしないとうまく描画できない。CSS の width, height は代用にならない。
NG: <canvas id="c"></canvas> #c { width: 640px; height: 400px; } OK: <canvas id="c" width="640" height="400"></canvas>
画像はプリロード必須
今回は以下のような関数を書いた。
var preloadImages = function (srcs) { if (!srcs.length) { return; } var dfd = $.Deferred(); var imgs = []; for (var i=0, l=srcs.length; i<l; i++) { var img = new Image(); img.src = srcs[i]; imgs.push(img); } var check = function () { for (var i=0, l=imgs.length; i<l; i++) { if (imgs[i].complete !== true) { setTimeout(check, 250); return false; } } dfd.resolve(imgs); }; check(); return dfd.promise(); }
画像はすべて別々に image オブジェクトを作る
それらを順に drawImage() する。そうしないと Chrome ではうまく描画できない。Firefox では同じ image オブジェクトを使い回しても描画できた。
// NG: var srcs = [ '0.png', '2.png' .. '100.png' ] var img = new Image(); preloadImages(srcs).done(function () { for (var i=0, l=srcs.length; i<l; i++) { img.src = srcs[i]; ctx.drawImage(img, 0, 0); } }); // OK: var srcs = [ '0.png', '2.png' .. '100.png' ]; preloadImages(srcs).done(function () { for (var i=0, l=srcs.length; i<l; i++) { var img = new Image(); img.src = srcs[i]; ctx.drawImage(img, 0, 0); } });