简体   繁体   English

为什么在canvas上绘制很多元素时页面开始卡顿?

[英]Why does the page start to lag when drawing many elements on the canvas?

I'm creating a game, and I need to draw) some elements at the top of the <canvas> , but the more elements appear, the more lag the page itself.我正在创建一个游戏,我需要在<canvas>的顶部绘制一些元素,但是出现的元素越多,页面本身的滞后性就越大。 I found this example where a lot of circles appear, but everything works fine - JSFiddle .我发现这个例子中出现了很多圆圈,但一切正常 - JSFiddle Can someone tell me how to optimize my case?有人可以告诉我如何优化我的案例吗?

"use strict";

/*Determing canvas*/
window.onload = () => {
    const canvas = document.getElementById("canvas"),
        ctx = canvas.getContext('2d'),
        endTitle = document.getElementById('gameover');
    let spawnRate = 300,
        lastspawn = -1;

    class Wall {
        /*Getting values*/
        constructor(x, y, width, height, speed) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.speed = speed;
        }
        /*Draw rectangle*/
        draw() {
            ctx.beginPath();
            ctx.fillStyle = "#000000";
            ctx.fillRect(this.x, this.y, this.width, this.height)
        }
    }

    /*Making walls*/
    let walls = [];

    /*Spawn walls endlessly*/
    function spawnWalls() {
        const wall_x = Math.floor(Math.random() * (canvas.width - 20)) + 10
        const wall_y = 0
        for (let i = 0; i < 200; i++) {
            walls.push(new Wall(wall_x, wall_y, 10, 10, 10))
        }
    }
    
    /*Update game*/
    function refresh() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        let time = Date.now()
        if (time > (lastspawn + spawnRate)) {
            lastspawn = time;
            spawnWalls();
            spawnRate -= 10;
        }
        walls.forEach(wall => wall.draw())
        for (let j of walls) {
            j.y += j.speed;
            j.draw();
        };
    };
    let interval = setInterval(refresh, 50);                                                                                                   

Walls is too big. Walls太大了。

It looks like you're never removing old walls, so they are continuing to be drawn well after they have been removed from the canvas.看起来您永远不会移除旧墙,因此在将它们从 canvas 中移除后,它们会继续被很好地绘制。 In your Refresh function, check if the wall has passed the canvas size and if so, remove that from the walls array.在您的 Refresh function 中,检查墙壁是否已通过 canvas 大小,如果是,请将其从walls阵列中删除。

EDIT:编辑:

I've added your 'remove' code from the comment.我已经从评论中添加了您的“删除”代码。

Another easy win is to stop using new Date() because of who knows what, probably time zones and localization, dates are very expensive to instantiate.另一个简单的胜利是停止使用new Date()因为谁知道什么,可能是时区和本地化,日期实例化非常昂贵。 However modern browsers offer a performance API, and that can tell you the time since page load, which seems to have a substantial improvement on your existing performance.然而,现代浏览器提供了 API 的性能,它可以告诉您自页面加载以来的时间,这似乎对您现有的性能有很大的改进。

 "use strict"; /*Determing canvas*/ window.onload = () => { const canvas = document.getElementById("canvas"), ctx = canvas.getContext('2d'), endTitle = document.getElementById('gameover'); let spawnRate = 300, lastspawn = -1; endTitle.style.display = "none"; canvas.width = window.innerWidth; canvas.height = window.innerHeight; /*Classes*/ class Player { /*Get player info*/ constructor(x, y, width, height, speed) { this.x = x; this.y = y; this.width = width; this.height = height; this.speed = speed; } /*Draw player*/ draw() { ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.fillRect(this.x, this.y, this.width, this.height); } /*Move player*/ move() { } }; class Wall { /*Getting values*/ constructor(x, y, width, height, speed) { this.x = x; this.y = y; this.width = width; this.height = height; this.speed = speed; } /*Draw rectangle*/ draw() { ctx.beginPath(); ctx.fillStyle = "#000000"; ctx.fillRect(this.x, this.y, this.width, this.height) } } /*Defining players*/ let player_01 = new Player(20, 70, 20, 20, 10); let player_02 = new Player(50, 500, 20, 20, 10); let players = []; players.push(player_01); /*Making walls*/ let walls = []; /*Spawn Walls for infinity*/ function spawnWalls() { const wall_x = Math.floor(Math.random() * (canvas.width - 20)) + 10 const wall_y = 0 for (let i = 0; i < 200; i++) { walls.push(new Wall(wall_x, wall_y, 10, 10, 10)) } } /*Update game*/ function refresh() { ctx.clearRect(0, 0, canvas.width, canvas.height); let time = performance.now() if (time > (lastspawn + spawnRate)) { lastspawn = time; spawnWalls(); spawnRate -= 10; } walls.forEach(wall => wall.draw()) outOfWindow() for (let i of players) { i.draw(); }; for (let j of walls) { if (jy > canvas.height) { walls.shift(j) } jy += j.speed; j.draw(); if (player_01.height + player_01.y > jy && j.height + jy > player_01.y && player_01.width + player_01.x > jx && j.width + jx > player_01.x) { clearInterval(interval); endTitle.style.display = "flex"; }; }; }; let interval = setInterval(refresh, 50); /*Move players on keypress*/ for (let i of players) { window.addEventListener("keydown", (event) => { let key = event.key.toLowerCase(); if (key == "w") iy -= i.speed; else if (key == "s") iy += i.speed; else if (key == "a") ix -= i.speed; else if (key == "d") ix += i.speed; }) } /*Check if player out of the window*/ function outOfWindow() { for (let i of players) { if (ix < 0) ix = 0; else if (ix + i.width > canvas.width) ix = canvas.width - i.width; else if (iy < 0) iy = 0; else if (iy + i.height > canvas.height) iy = canvas.height - i.height; } } }
 #gameover { position: absolute; width: 100%; height: 100%; justify-content: center; align-items: center; flex-direction: column; background-color: rgba(0, 0, 0, .5); }
 <div id="gameover"> <h2>The Game Is Over</h2> <button onclick="restart()">Try again!</button> </div> <canvas id="canvas"></canvas>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM