Chrome 瀏覽器在 Canvas 繪圖中存在明顯的錯誤。以下代碼
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.setTransform(2, 0, 0, 2, 0, 0);
ctx.beginPath();
const arr = [
["moveTo",7,209],
["lineTo",6318,403],
["lineTo",15786,453],
["lineTo",18942,451],
["lineTo",22098,28]
];
ctx.beginPath();
arr.forEach(item => {
if (item[0] === 'lineTo') {
ctx.lineTo(item[1], item[2]);
} else if (item[0] === 'moveTo') {
ctx.moveTo(item[1], item[2]);
}
})
ctx.strokeStyle = 'red'
ctx.stroke();
<canvas
id="canvas"
width=800
height=800
style="width: 400px; height: 400px"
>
</canvas>
Chrome94中的結果是這樣的: Chrome94&95
Safari中相同的代碼是這樣的: Safari
那么有沒有辦法避免chrome中的這個錯誤?
uj5u.com熱心網友回復:
此錯誤已在最新的 Canary 97 中修復。
這顯然是您巨大坐標的舍入問題。因此,為了避免它,請盡可能避免使用大坐標。
否則,如果您確實必須使用解決方法,則可以強制畫布使用軟體渲染。但這會完全減慢您的畫布速度,應盡可能避免。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d', {
willReadFrequently: true // force software rendering (in 95 ?)
});
ctx.setTransform(2, 0, 0, 2, 0, 0);
ctx.beginPath();
const arr = [
["moveTo",7,209],
["lineTo",6318,403],
["lineTo",15786,453],
["lineTo",18942,451],
["lineTo",22098,28]
];
ctx.beginPath();
arr.forEach(item => {
if (item[0] === 'lineTo') {
ctx.lineTo(item[1], item[2]);
} else if (item[0] === 'moveTo') {
ctx.moveTo(item[1], item[2]);
}
})
ctx.strokeStyle = 'red';
// in case willReadFrequently didn't make it
if (ctx.getContextAttributes && !ctx.getContextAttributes().willReadFrequently) {
ctx.getImageData(0, 0, 1, 1);
}
ctx.stroke();
<canvas
id="canvas"
width=800
height=800
style="width: 400px; height: 400px"
>
</canvas>
因此,最好的方法是嘗試重現錯誤并事先檢查您是否使用有問題的瀏覽器:
const isBuggyBrowser = (() => {
const ctx = document.createElement("canvas").getContext('2d');
// move the bug toward the top left corner
ctx.setTransform(2, 0, 0, 2, -900, -900);
// removed some fluff
const arr = [
[7,209],
[6318,403],
[15786,453],
[18942,451],
[22098,28]
];
// lineTo from an empty subpath is auto-converted to moveTo
arr.forEach(([x,y]) => ctx.lineTo(x, y));
ctx.stroke();
// not transparent
return !!ctx.getImageData(0, 1, 1, 1).data[3]
})();
console.log( "is your browser buggy?", isBuggyBrowser );
現在您可以有條件地應用解決方法:
顯示代碼片段
const isBuggyBrowser = (() => {
const ctx = document.createElement("canvas").getContext('2d');
// move the bug toward the top left corner
ctx.setTransform(2, 0, 0, 2, -900, -900);
// removed some fluff
const arr = [
[7,209],
[6318,403],
[15786,453],
[18942,451],
[22098,28]
];
// lineTo from an empty subpath is auto-converted to moveTo
arr.forEach(([x,y]) => ctx.lineTo(x, y));
ctx.stroke();
// not transparent
return !!ctx.getImageData(0, 1, 1, 1).data[3]
})();
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d', {
willReadFrequently: isBuggyBrowser
});
ctx.setTransform(2, 0, 0, 2, 0, 0);
ctx.beginPath();
const arr = [
["moveTo",7,209],
["lineTo",6318,403],
["lineTo",15786,453],
["lineTo",18942,451],
["lineTo",22098,28]
];
ctx.beginPath();
arr.forEach(item => {
if (item[0] === 'lineTo') {
ctx.lineTo(item[1], item[2]);
} else if (item[0] === 'moveTo') {
ctx.moveTo(item[1], item[2]);
}
})
ctx.strokeStyle = 'red';
// in case willReadFrequently didn't make it
if (isBuggyBrowser && ctx.getContextAttributes &&
!ctx.getContextAttributes().willReadFrequently) {
ctx.getImageData(0, 0, 1, 1);
}
ctx.stroke();
<canvas
id="canvas"
width=800
height=800
style="width: 400px; height: 400px"
>
</canvas>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/328976.html
標籤:javascript html 谷歌浏览器 帆布
