Entries tagged “javascript”

Serialization of HTML5 web worker postMessage parameters in webkit

I played around with html5 web workers today. I quickly ran into an issue with chrome. Chrome (and probably also Safari) limit the messages that can be passed around to strings. The spec seems to allow arbitrary objects though, which works in firefox. Luckily Chrome supports native json, so here is a quick workaround.

// in the worker
if(navigator.userAgent.indexOf('WebKit')) {
    var _postMessage = postMessage;
    postMessage = function(data) {
        _postMessage(JSON.stringify(data));
    }
}
// in the page
worker.onmessage = function(e) {
    // assign it to a variable, e.data seems to be read-only
    var data = e.data;
    if(navigator.userAgent.indexOf('WebKit') != -1) {
       data = JSON.parse(data);
    }
// ..

In the worker monkey patching is easily possible. But I'm not aware of a nice way to intercept events so, I just put the decoding in the event handler. If I would need this in a lot of places I would probably write a higher order function the decode the argument.

Flip Images using HTML5 Canvas

You can flip an Image using HTML5 like this:

// flip x axis
ctx.scale(-1, 1);
ctx.drawImage(img, x, y);
// flip it back again
ctx.scale(-1, 1);

You can flip along the y axis in the same way. I'm note sure how fast this transformation is, in practice so you might need to cache it if you are doing realtime graphics.

Hand drawn lines using javascript canvas


For an upcoming game I'm working on I want the lines to look hand drawn. I found a nice paper on the subject. My algorithm is inspired by that paper, but not an exact implementation. But the results look good anyway. I also wrote a method to draw circles, but it needs improvement. Please let me know if you use it anywhere. :)

// randomize a variable
function fuzz(x, f){
    return x + Math.random()*f - f/2;
}

// estimate the movement of the arm
// x0: start
// x1: end
// t: step from 0 to 1
function handDrawMovement(x0, x1, t){
    return x0 + (x0-x1)*(
            15*Math.pow(t, 4) -
            6*Math.pow(t, 5) -
            10*Math.pow(t,3)
    )
}

// hand draw a circle
// ctx: Context2D
// x, y: Coordinates
// r: radius
function handDrawCircle(ctx, x, y, r){
    var steps = Math.ceil(Math.sqrt(r)*3);

    // fuzzyness dependent on radius
    var f = 0.12*r;

    // distortion of the circle
    var xs = 1.0+Math.random()*0.1-0.05;
    var ys = 2.0-xs;

    ctx.moveTo(x+r*xs, y);

    for(var i = 1; i <= steps; i++)
    {
        var t0 = (Math.PI*2/steps)*(i-1);
        var t1 = (Math.PI*2/steps)*i;
        var x0 = x+Math.cos(t0)*r*xs;
        var y0 = y+Math.sin(t0)*r*ys;
        var x1 = x+Math.cos(t1)*r*xs;
        var y1 = y+Math.sin(t1)*r*ys;

        ctx.quadraticCurveTo(fuzz(x0, f), fuzz(y0, f), x1, y1);
        ctx.moveTo(x1, y1);
    }
}

// inspired by this paper http://iwi.eldoc.ub.rug.nl/FILES/root/2008/ProcCAGVIMeraj/2008ProcCAGVIMeraj.pdf
function handDrawLine(ctx, x0, y0, x1, y1){
    ctx.moveTo(x0, y0)

    var d = Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))

    var steps = d/25;
    if(steps < 4) {
        steps = 4;
    }

    // fuzzyness
    var f = 8.0;
    for(var i = 1; i <= steps; i++)
    {
        var t1 = i/steps;
        var t0 = t1-1/steps
        var xt0 = handDrawMovement(x0, x1, t0)
        var yt0 = handDrawMovement(y0, y1, t0)
        var xt1 = handDrawMovement(x0, x1, t1)
        var yt1 = handDrawMovement(y0, y1, t1)
        ctx.quadraticCurveTo(fuzz(xt0, f), fuzz(yt0, f), xt1, yt1)
        ctx.moveTo(xt1, yt1)
    }
}

New Game: JS WARS

Today I release JS WARS to the public. JS WARS is a side scrolling shooter programmed using JavaScript and the html5 canvas/audio elements. All the graphics and sounds were created using free software (blender, gimp and csound). Go check it out! I know you want to!.


Emulating Canvas fillText in Firefox 3.0

After running into problems with canvas-text I wrote this code to emulate the html5 canvas text methods in firefox 3.0. It's not a complete implementation but it should be enough for most cases.

if(proto.mozMeasureText && !proto.measureText) {
    proto.__defineSetter__('font', function(x) { this.mozTextStyle = x;});
    proto.__defineGetter__('font', function() { return this.mozTextStyle;});
}
if(proto.mozMeasureText && !proto.measureText) {
    proto.measureText = function(text) { return {'width': this.mozMeasureText(text)}; };
}
if(proto.mozPathText && !proto.strokeText) {
    proto.strokeText = function(text, x, y) {
        this.translate(x, y);
        this.mozPathText(text);
        this.stroke();
        this.translate(-x, -y);
    };
}
if(proto.mozDrawText && !proto.fillText) {
    proto.fillText = function(text, x, y) {
        this.translate(x, y);
        this.mozDrawText(text);
        this.translate(-x, -y);
    };
}

Canvas Tag drawImage performance

Today I was tracking down a strange performance bottleneck in a html5 canvas based application I'm writing. In some occasions calling drawImage on a canvas was very slow. It took me a little while to figure out the reason. drawImage was always getting very slow when floats were used as coordinates. Let me give you a little example:

// slow
ctx.drawImage(img, 10.1, 3.4);
// fast
ctx.drawImage(img, 10, 3);

I guess the browsers are doing some kind of expensive resampling when float coordinates are used. After changing all the drawImage calls to pass integers the rendering was a lot faster.