Skip to content Skip to sidebar Skip to footer

For Loop Inside Another For Loop Crashes In Javascript

I want to randomly generate a color for each pixel in the canvas however my loop seems to crash the browser and I cannot figure out why? I have tried reducing the loop to a static

Solution 1:

You’re redrawing the path every time you add a line to it. That’s quadratic and not necessary. (Quadratic is a problem when you have 20,000+ lines.)

Draw once:

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();

And when you want to draw in multiple colours, start a new path every for each line:

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 seems like a better choice for a canvas method to draw a pixel, though:

constgetRandomColor = () =>
    '#' + (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);
<canvasid="canvas"></canvas>

And finally, putting image data probably gives the best performance.

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

const start = performance.now();

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

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

const randomRGBA = newUint8ClampedArray(random32.buffer);

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

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

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

(Fun fact: crypto.getRandomValues is faster than this in practice, but not a good choice.)

Post a Comment for "For Loop Inside Another For Loop Crashes In Javascript"