我正在使用畫布繪制標記(在 SVG 中)數百(有時是數千)次。畫布的大小為 300x300 像素,SVG 為 18x25 像素。
代碼非常直接,我有一個 for 回圈,我在畫布上繪制標記:
drawNewTile = (canvas, points) => {
const drawn = {};
const context = canvas.getContext('2d');
if (points.length === 0) return;
for (let i = points.length; i -= 1;) {
const [x, y] = points[i];
if (!drawn[`${x}:${y}`]) {
drawn[`${x}:${y}`] = true;
this.drawMarker(context, x, y);
}
}
};
drawMarker = (context, x, y) => {
const x_ = Math.floor(x - this.MARKER_WIDTH / 2 this.MAX_DIMENSION_OF_MARKER);
const y_ = Math.floor(y - this.MARKER_HEIGHT this.MAX_DIMENSION_OF_MARKER);
context.drawImage(this.marker, x_, y_, this.MARKER_WIDTH, this.MARKER_HEIGHT);
};
我已經進行了一些優化:比如 for 回圈,只繪制那些尚未繪制的點,使用整數坐標等。
在那之后,我得到了一些不錯的結果,但是我的頁面在谷歌瀏覽器上有點卡住了。盡管如此,令我驚訝的是,在 Firefox 中,它運行得非常快,真的非常快。因此,我使用 Google Chrome 的性能選項卡進行了一些挖掘,發現我的代碼使用了大量 CPU,而且速度很慢。
我還發現這篇文章說 Chrome 使用一些啟發式方法來確定它是使用 CPU 還是 GPU 來繪制畫布。
所以,我的問題是,如何在 Chrome 上強制使用 GPU?我可以設定任何標志或類似的東西嗎?您還有其他方法可以加快繪圖程序嗎?
uj5u.com熱心網友回復:
問題在于 Chrome 顯然將 SVG 影像保留在 CPU 中,并在每次新呼叫drawImage().
簡單地自己光柵化它會使 Chrome 的性能立即提高。
為此,請使用該createImageBitmap()方法,該方法將創建一個 ImageBitmap,瀏覽器將能夠將其直接存盤在 GPU 的記憶體中。
Safari 剛剛在他們最新版本的瀏覽器中公開了這個方法,所以你可能仍然想要使用 polyfill。雖然在這種情況下,簡單地在畫布上繪圖就足夠了,但我制作了這樣一個 polyfill,其中包含一些大多數瀏覽器尚不支持的功能。
(async () => {
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const select = document.querySelector("select");
const html_img = new Image();
const svg_str = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 25" width="18" height="25">
<circle cx="9" cy="9" r="6"/>
</svg>`;
const svg_blob = new Blob([svg_str], {
type: "image/svg xml"
});
ctx.font = "20px sans-serif";
ctx.fillStyle = "red";
html_img.src = URL.createObjectURL(svg_blob);
const sources = {
html_img,
bitmap: await createImageBitmap(svg_blob)
};
const times = [];
await html_img.decode();
anim();
function anim() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let y = 0; y < canvas.width; y = 10) {
for (let x = 0; x < canvas.width; x = 5) {
ctx.drawImage(sources[select.value], x, y);
}
}
requestAnimationFrame(anim);
// ultra rough FPS counter
const now = performance.now();
while (times.length > 0 && times[0] <= now - 1000) {
times.shift();
}
times.push(now);
fps = times.length;
ctx.fillText(fps "FPS", 30, 30);
}
})();
<!-- createImageBitmap polyfill for old browsers --> <script src="https://cdn.jsdelivr.net/gh/Kaiido/createImageBitmap/dist/createImageBitmap.js"></script>
source: <select>
<option value="bitmap">ImageBitmap</option>
<option value="html_img">HTMLImage</option>
</select><br>
<canvas width="300" height="300"></canvas>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314690.html
