Java中另一个for循环内的for循环崩溃

时间:2019-06-21 04:22:52

标签: javascript loops canvas

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

我尝试将循环减少为静态数(X = 10 x Y = 100),这似乎可行。但是,结果要花几秒钟才能显示在屏幕上(尽管我的测试显示运行时间为10ms)

我是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>

不加载,崩溃浏览器窗口

1 个答案:

答案 0 :(得分:1)

每次向其添加线条时,您都将重新绘制路径。这是二次方的,不是必须的。 (当您的行数超过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似乎是画布方法绘制像素的更好选择,

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在实践中比这快,但不是一个好选择。)