ResizeObserverを使ってCanvas要素の再レンダリングをする
ResizeObserverは、要素サイズの変化を監視して変更が発生したらcallbackを呼び出すオブジェクトだ。
Canvas APIは、Canvas要素のサイズ(widthやheight)が変更されても再描画しないため、正しく描画されない。そんなときにResizeObserverを使ってCanvas要素のサイズが変更されたら再描画する処理を実装できる。
/**
* entries: ResizeObserverEntryの配列で、それぞれの変更後のサイズを取得できる
* observer: ResizeObserverオブジェクト自身の参照で、observer.disconnect()などの用土で使う
*/
const observer = new ResizeObserver((entries, observer) => {
for (const entry of entries) {
const { inlineSize: width, blockSize: height } = entry.contentBoxSize[0]
// ...
}
})
const canvas = document.getElementById('#canvas')
observer.observe(canvas)
ResiseObserverEntryは以下のプロパティを持っている。
- borderBoxSize: border-boxサイズを含むオブジェクトの配列
- blockSize
- inlineSize
- contentBoxSize: content-boxサイズを含むオブジェクトの配列
- blockSize
- inlineSize
- devicePixelContentBoxSize: デバイスピクセル単位のサイズを含むオブジェクト
- blockSize
- inlineSize
- contentRect: DOMRectReadOnlyのオブジェクト
- target: 監視対象の要素
Canvas要素はリサイズしても再描画されない
<div class="resizable">
<canvas id="canvas"></canvas>
</div>
function render(canvas) {
const ctx = canvas.getContext('2d')
// 描画処理
}
const canvas = document.getElementById('#canvas')
render(canvas)
リサイズを監視してCanvas要素の再描画をする
<div class="resizable">
<canvas id="canvas"></canvas>
</div>
const canvas = document.getElementById('#canvas')
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const { inlineSize, blockSize } = entry.contentBoxSize[0]
canvas.width = inlineSize
canvas.height = blockSize
render(canvas)
}
})
observer.observe(canvas)