问题描述
我发现了这个老问题,但无法重现所描述的问题 Html canvas 1600x1200 screen tearing。
从 canvas
回调更新 setTimeout
应该产生屏幕撕裂是有道理的。但即使闪烁非常明显,似乎也不会发生撕裂。这是一个小演示:codepen
我在 Chrome 和 Safari 中看不到任何撕裂。当然浏览器不会使用 setTimeout
进行 VSync。那么这里发生了什么?
我在画布更新中添加了延迟,因此在更新过程中更可能发生缓冲区交换,但这里没有运气。
const STRIPE_WIDTH = 50;
const STEP = 4;
let canvas = document.createElement('canvas');
canvas.style.width = '100%';
canvas.style.height = '100%';
document.body.appendChild(canvas);
let ctx = canvas.getContext('2d');
let pos = 0;
function render(){
ctx.clearRect(0,canvas.width,canvas.height);
let width = Math.ceil(canvas.width/STRIPE_WIDTH) * STRIPE_WIDTH;
ctx.fillStyle = 'black';
for(i = pos; i < width; i+=STRIPE_WIDTH){
for(j = 0; j < canvas.height; j++){
ctx.fillRect(i,j,STRIPE_WIDTH/2,1);
}
}
for(i = pos; i > 0; i-=STRIPE_WIDTH){
for(j = 0; j < canvas.height; j++){
ctx.fillRect(i - STRIPE_WIDTH,1);
}
}
pos = pos + STEP;
setTimeout(render,1000/60);
}
render();
解决方法
是的,画布渲染仍然与文档渲染相关,它本身与显示器的 v-sync 同步,因此您不应看到任何撕裂。
您可以通过将上下文的 desynchronized
属性设置为 true
来禁用此功能。
const low_latency_ctx = canvas.getContext("2d",{ desynchronized: true });
但是,目前只有 Chrome 操作系统和 Windows 上的 Chrome 支持此功能。由于我手头没有这样的配置,很遗憾我无法自己编写演示...