javascript - Javascript 中的 For 循环在另一个 for 循环中崩溃

标签 javascript loops canvas

我想为 Canvas 中的每个像素随机生成一种颜色,但是我的循环似乎使浏览器崩溃,我不知道为什么?

我尝试将循环减少到静态数(X = 10 x Y=100),它似乎有效。然而,结果需要几秒钟的时间才能显示在屏幕上(尽管我的测试显示运行时间为 10 毫秒)

我是 javascript/html 的新手,所以这可能是一个明显的解决方案,但是非常感谢任何帮助。

//"use strict";

    // SELECT THE CANVAS ELEMENT FROM THE HTML PAGE AND NAME IT 'WORLD'
    let world = document.querySelector("canvas");


    // SET THE CANVAS HEIGHT/WIDTH TO THE WINDOW INNER X/Y
    world.width = window.innerWidth;
    world.height = window.innerHeight;

    let context = world.getContext("2d"); 


    // GET PERFORMANCE TEST VALUE BEFORE LOOP
    let t0 = performance.now();

    let x=0;
    let y=0;

    // LOOP THROUGH THE CANVAS STARTING AT FIRST PIXEL OF TOP ROW MOVING TO THE LAST PIXEL OF THE TOP ROW AND FILL, THEN MOVE TO THE NEXT LINE AND REPEAT FILL FOR EACH ROW UNTIL CANVAS IS COLORED

    for (y=0; y < world.height; y++)
    {
	    //TODO: ADD RANDOM RGB COLOR TO STROKE
	    context.lineTo(x,y);
	    context.stroke();

	    for (x=0; x < 10; x++){
		    //TODO: ADD RANDOM RGB COLOR TO STROKE
		    context.lineTo(x,y);
		    context.stroke();
	    }
    }

    // GET PERFORMANCE TEST VALUE AFTER LOOP
    let t1 = performance.now();

    // LOG THE TOTAL MILLISECONDS OF THE LOOP
    console.log("Total Time" + (t1-t0) + " milliseconds");

    // GENERATE A RANDOM NUMBER BASED ON THE WINDOW INNER WIDTH
    function getRandomX(){
    	return Math.random() * window.innerWidth;
    }

    // GENERATE A RANDOM NUMBER BASED ON THE WINDOW INNER HEIGHT
    function getRandomY(){
    		return Math.random() * window.innerHeight;
    }

    // GENERATE A RANDOM NUMBER BETWEEN 0 - 255
    function getRandomRGB(){
    		return Math.Random() * 255;
    }
<canvas></canvas>

无法加载,浏览器窗口崩溃

最佳答案

每次向路径添加线条时,都会重新绘制路径。这是二次的,而且没有必要。 (当您有 20,000 多条线时,二次就会出现问题。)

绘制一次:

let x = 0;

for (let y = 0; y < world.height; y++) {
    context.lineTo(x, y);

    for (x = 0; x < 10; x++) {
        context.lineTo(x, y);
    }
}

context.stroke();

当您想用多种颜色绘制时,请为每行开始一条新路径:

let x = 0;

for (let y = 0; y < world.height; y++) {
    //TODO: ADD RANDOM RGB COLOR TO STROKE
    context.lineTo(x, y);
    context.stroke();
    context.beginPath();
    context.moveTo(x, y);

    for (x = 0; x < 10; x++) {
        //TODO: ADD RANDOM RGB COLOR TO STROKE
        context.lineTo(x, y);
        context.stroke();
        context.beginPath();
        context.moveTo(x, y);
    }
}
不过,

fillRect 似乎是 Canvas 方法绘制像素的更好选择:

const getRandomColor = () =>
    '#' + (Math.random() * 0x1000000 >>> 0).toString(16);

const world = document.getElementById('canvas');
const context = world.getContext('2d');

const start = performance.now();

for (let y = 0; y < world.height; y++) {
    for (let x = 0; x < world.width; x++) {
        context.fillStyle = getRandomColor();
        context.fillRect(x, y, 1, 1);
    }
}

console.log(performance.now() - start);
<canvas id="canvas"></canvas>

最后,放入图像数据可能会提供最佳性能。

const world = document.getElementById('canvas');
const context = world.getContext('2d');

const start = performance.now();

const {width, height} = world;
const random32 = new Uint32Array(width * height);

for (let i = 0; i < random32.length; i++) {
    random32[i] = Math.random() * 0x100000000 >>> 0;
}

const randomRGBA = new Uint8ClampedArray(random32.buffer);

for (let i = 3; i < randomRGBA.length; i += 4) {
    randomRGBA[i] = 255;
}

const imageData = new ImageData(randomRGBA, width, height);
context.putImageData(imageData, 0, 0);

console.log(performance.now() - start);
<canvas id="canvas"></canvas>

(有趣的事实:crypto.getRandomValues 在实践中比这更快,但不是一个好的选择。)

关于javascript - Javascript 中的 For 循环在另一个 for 循环中崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56696807/

相关文章:

javascript - WinForms 应用程序中的地理定位

javascript - 在循环 + Nodejs 内使用带有 async/await 的循环

algorithm - 我在哪里可以了解如何以数学方式为 HTML5 Canvas 表示液体?

Android:如何使用 Canvas /绘制位图缩放位图以适合屏幕大小?

javascript - 如何在元素中包含的 Protractor 测试中获取div编号/计数

javascript - Chosen JS - 将optgroup添加到所选项目

javascript - 当属性是可选的时,如何在 Typescript 中解构对象?

Python:在没有列表的情况下取第一个字符

python - 如何在 while 循环中汇总某个范围内的整数

javascript - 意想不到的颜色?