Для цикла внутри другого цикла для цикла в Javascript - PullRequest
0 голосов
/ 21 июня 2019

Я хочу случайным образом сгенерировать цвет для каждого пикселя на холсте, однако мой цикл, похоже, приводит к сбою браузера, и я не могу понять, почему?

Я попытался уменьшить цикл до статического числа (X =10 х 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>

Не загружается, вылетает окно браузера

1 Ответ

1 голос
/ 21 июня 2019

Вы перерисовываете путь каждый раз, когда добавляете к нему линию. Это квадратично и не обязательно. (Квадратичная проблема, если у вас более 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 быстрее, чем это на практике, но не лучший выбор.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...