从 setTimeout 更新画布时无法出现屏幕撕裂

问题描述

我发现了这个老问题,但无法重现所描述的问题 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 支持此功能。由于我手头没有这样的配置,很遗憾我无法自己编写演示...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...