Javascript Canvas 画框时闪烁

Javascript Canvas Flashing When Drawing Frames

几天来一直遇到这个问题,不确定为什么我在 canvas 上呈现的文本闪烁得太多。我正在使用 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>

您看到的闪烁是循环代码的结果,您在删除元素时跳过了数组的元素(需要删除元素 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>