canvasでの描画を最適化する方法の一つとして、「プリレンダリング」がある。
プリレンダリングとは、ページに表示しないcanvas要素(以降"オフスクリーンcanvas"と呼ぶ)を作って事前に色々描画しておき、オフスクリーンcanvas自体をメインのcanvasに描画するという手法である。
プリレンダリングについてはここに詳しく書いてある。
また、canvasをCSSで拡大していたり高解像度のデバイスを使っていたりすると、canvasがぼやけてしまう。
そんなときはwindow.devicePixelRatio
を使ってcanvasの描画サイズを拡大してあげるとイイカンジになる。
window.devicePixelRatio
についてはここに詳しく書いてある。
さて、オフスクリーンcanvasを使うと、window.devicePixelRatio
で解像度を調整していても、オフスクリーンcanvasを描画した部分がぼやけてしまうことがある。
そんなときはオフスクリーンcanvasの描画サイズも拡大してあげればよい。
const appSize = {width: 200, height: 300};//200×300の大きさのアプリを作りたい。
/* <canvas id="main-canvas"></canvas>がすでにページにあるものとする。 */
const mainCanvas = document.getElementById('main-canvas');
const resolution = window.devicePixelRatio || 1;//デバイスの解像度
//CSSスタイルでのcanvasの大きさ(px)を取得
const styleWidth = mainCanvas.clientWidth;
const styleHeight = mainCanvas.clientHeight;
//メインcanvasの描画サイズを変更
mainCanvas.width = styleWidth * resolution;
const appCanvasRatio = mainCanvas.width/appSize.width;//アプリの大きさとcanvasの描画サイズの比
//コンテキストの拡大
const cxt = mainCanvas.getContext('2d');
cxt.scale(appCanvasRatio, appCanvasRatio);
//オフスクリーンcanvasの準備
const offscreenCanvas = document.createElement('canvas');
//オフスクリーンcanvasの描画サイズ変更 ただし適したサイズ(小さい方がいい)にしないと結果重くなってオフスクリーンの意味がなくなる
offscreenCanvas.width = mainCanvas.width;
offscreenCanvas.height = mainCanvas.height;
//オフスクリーンcanvasのコンテキストも拡大
const ocxt = offscreenCanvas.getContext('2d');
ocxt.scale(appCanvasRatio, appCanvasRatio);
/*
ocxtでの描画処理
*/
//オフスクリーンcanvasをメインcanvasに描画
const offX = 30;//オフスクリーンを描画する座標位置
const offY = 30;
const ratioInverse = 1/appCanvasRatio;//逆数
const wid = offscreenCanvas.width;
const hei = offscreenCanvas.height;
cxt.drawImage(offscreenCanvas,
0, 0, wid, hei,
offX, offY, wid*ratioInverse, hei*ratioInverse);
cxtもocxtも拡大しているため、オフスクリーンcanvasを写し取るときのサイズはappCanvasRatio
の逆数倍にしないといけない。
これでオフスクリーンcanvasの解像度もイイカンジにすることができる。
もしcanvasのスタイルをブラウザの大きさに対してレスポンシブにしているときは、document.addEventListener('resize', リサイズ処理)
で上手いことやればよい。