Drawing HTML5 canvas in real time

Question: How can I make putImageData()

the canvas update in real time since different parts of the image have been calculated?


I am working on a JavaScript / TypeScript application to draw a Mandelbrot set on an HTML5 element <canvas>

. Math and details aside, my app draws a set very well. However, if you are familiar with rendering a set, you know that this can be time consuming.

It will drag on after a few seconds, but until the canvas is completely empty, the image will appear. I am looking for a way to draw each line as it is calculated with putImageData()

. Here's what I'm trying:

// part of the class definition
private Context: CanvasRenderingContext2D;
private ImageData: ImageData;
private Pixels: number[];

constructor() {
    var c: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("can");

    this.Context = c.getContext("2d");
    this.ImageData = this.Context.createImageData(this.Size.Width, 1);
    this.Pixels = this.ImageData.data;
}

public draw() {
    // tried this... does not help
    // var handler = function(m: Mandelbrot) {
    //    m.Context.putImageData(m.ImageData, 0, i)
    // };

    for(var i: number = 0; i < this.Size.Height; ++i) {    // Loop over each row
        for(var j: number = 0; j < this.Size.Width; ++j) { // Calc px. for one row
            // all the math to compute the set... (works)

            this.setPixelColor(j, color); // sets a color in this.Pixels (works)
        }

        // setTimeout(handler(this), 0); // does not help
        this.Context.putImageData(this.ImageData, 0, i); // Draw the row on the canvas?
    }
}

      

Be that as it may, the function putImageData()

called after the line in the image was evaluated, only the image is displayed after the entire image has been created.

How can I make putImageData()

the canvas update in real time since each row has been calculated?


Last updated non-working code:

var handler = function(m: Mandelbrot, i: number) {
    for (var j: number = 0; j < m.Size.Width; ++j) {
        // math

        m.setPixelColor(j, color);
    }

    m.Context.putImageData(m.ImageData, 0, i);
};

var that: Mandelbrot = this;

for(var i: number = 0; i < this.Size.Height; ++i) {
    setTimeout(function() {
        handler(that, i)
    }, 0);
}

      


Working code, thanks to ekuusela:

var handler = function(m: Mandelbrot, i: number) {
    return function() {
        for (var j: number = 0; j < m.Size.Width; ++j) {
            // math

            m.setPixelColor(j, color);
        }

        m.Context.putImageData(m.ImageData, 0, i);
    }
};

for(var i: number = 0; i < this.Size.Height; ++i) {
    setTimeout(handler(this, i), 0);
}

      

+3


source to share


1 answer


Try to wrap putImageData

and calculate for one line to call setTimeout

to execute it asynchronously (post accept edit: see final code in question, it won't work as it i

will be undefined

in line putImageData

)



public draw() {
    var that = this;
    var drawRow = function() {
            for(var j: number = 0; j < that.Size.Width; ++j) { // Calc px. for one row
                that.setPixelColor(j, color); // sets a color in this.Pixels (works)
            }

            // TODO specify the dirty region in this call
            that.Context.putImageData(that.ImageData, 0, i); // Draw the row on the canvas?
        };
    for(var i: number = 0; i < this.Size.Height; ++i) {    // Loop over each row
        setTimeout(drawRow, 0);
    }
}

      

+3


source







All Articles