绘制帧时,Javascript画布闪烁问题

3

最近几天我一直遇到这个问题,不确定为什么我在画布上渲染的文本会闪烁。我正在使用requestAnimationFrame()函数,但它仍然在闪烁。

我的期望是让文本平滑地移动,并在完全移出屏幕后从数组中删除。

var canvas = document.getElementById("myCanvas");

var c = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

var w = canvas.width;
var h = canvas.height;

var texts = [];

window.addEventListener("load", init);

function init() {
    draw();
    mainLoop();
}


function mainLoop() {
    texts.push(createText("wow", "blue"));
    texts.push(createText("wow", "green"));
    texts.push(createText("wow", "red"));
    setTimeout(function() { mainLoop(); }, 100);
}

function Text(x, y, vx, vy, varText, theColor){
    this.x = x;
    this.y = y;
    this.vx = vx;
    this.vy = vy;
    this.color = theColor;
    this.draw = function() {
        drawStroked(varText, this.x, this.y, this.color);
    }
}

function drawStroked(text, x, y, color) {
    c.font = "30px bold Comic Sans MS";
    c.strokeStyle = 'black';
    c.lineWidth = 8;
    c.strokeText(text, x, y);
    c.fillStyle = color;
    c.fillText(text, x, y);
}

function createText(varText, color) {
    var x = (Math.random() * w / 2 ) + w/4;
    var y = (Math.random() * h / 2) + h/2;
    var vx = (Math.random() * .5) - .25
    var vy = -(Math.random() * 3) - 1

    return new Text(x, y, vx, vy, varText, color);
}

function draw() {
    c.clearRect(0, 0, c.canvas.width, c.canvas.height);
    for(var i = 0;i < texts.length; i++) {
        var currentText = texts[i];
        currentText.x += currentText.vx;
        currentText.y += currentText.vy;
        currentText.draw();

        if(currentText.x>w||currentText.x<0||currentText.y<10){
            texts.splice(i, 1);
        }
    }

    requestAnimationFrame(draw);
}
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
  <title>Game Screen</title>
</head>
<body>

<canvas id="myCanvas"></canvas>

</body>
</html>

1个回答

4
你看到的闪烁来自于你的循环代码,当你跳过数组元素进行删除操作时(需要删除第3个元素?你调用splice(3, 1),然后在索引4处继续循环。由于调用splice时数组会移动,所以你应该再次处理第3个元素)。 修复最简单的方法是倒序迭代数组。请注意,倒序迭代不太CPU高速缓存有效(因为每个数组访问都会导致高速缓存未命中),因此另一种解决方法是:
if(currentText.x>w||currentText.x<0||currentText.y<10){
            texts.splice(i--, 1); // decrement i after accessing and deleting
}

var canvas = document.getElementById("myCanvas");

var c = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

var w = canvas.width;
var h = canvas.height;

var texts = [];

window.addEventListener("load", init);

function init() {
    draw();
    mainLoop();
}


function mainLoop() {
    texts.push(createText("wow", "blue"));
    texts.push(createText("wow", "green"));
    texts.push(createText("wow", "red"));
    setTimeout(function() { mainLoop(); }, 100);
}

function Text(x, y, vx, vy, varText, theColor){
    this.x = x;
    this.y = y;
    this.vx = vx;
    this.vy = vy;
    this.color = theColor;
    this.draw = function() {
        drawStroked(varText, this.x, this.y, this.color);
    }
}

function drawStroked(text, x, y, color) {
    c.font = "30px bold Comic Sans MS";
    c.strokeStyle = 'black';
    c.lineWidth = 8;
    c.strokeText(text, x, y);
    c.fillStyle = color;
    c.fillText(text, x, y);
}

function createText(varText, color) {
    var x = (Math.random() * w / 2 ) + w/4;
    var y = (Math.random() * h / 2) + h/2;
    var vx = (Math.random() * .5) - .25
    var vy = -(Math.random() * 3) - 1

    return new Text(x, y, vx, vy, varText, color);
}

function draw() {
    c.clearRect(0, 0, c.canvas.width, c.canvas.height);
    for(var i = texts.length - 1;i >= 0; i--) {
        var currentText = texts[i];
        currentText.x += currentText.vx;
        currentText.y += currentText.vy;
        currentText.draw();

        if(currentText.x>w||currentText.x<0||currentText.y<10){
            texts.splice(i, 1);
        }
    }

    requestAnimationFrame(draw);
}
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
  <title>Game Screen</title>
</head>
<body>

<canvas id="myCanvas"></canvas>

</body>
</html>


太好了,谢谢你的回答和解释问题!我学到了新东西。感谢并保重! - Tenetri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接