Question

I'd been trying to write a small library in Javascript mainly for Canvas drawImage() method. The main purpose of the library is to pass array values instead of passing single values such as :

// srcPos=[0,0] , size=[90,90], dstPos=[50,50] 

function draw_image(context, image, srcPos, size, dstPos, size) {
    context.drawImage(image, srcPos[0], srcPos[1], size[0], size[1], dstPos[0], dstPos[1], size[0], size[1]);
}

but when i called this function jzz like this, I'm getting Uncaught ReferenceError :

var canvas = document.getElementById("display"),
    frame = canvas.getContext("2d");
var shipInfo = { center:[45, 45], size:[90, 90], radius: 35, angle:45 },
            shipImage = new Image(),
            pos = [40, 70];
shipImage.src = "ship.png";

function draw() {
    draw_image(frame, shipImage, shipInfo.size, pos, shipInfo.size);
}

window.onload = function() {
    draw();
}

And Is it possible to implement a method overriding the default drawImage() like this:

frame.draw_image(shipImage, srcPos, shipInfo.size, dstPos, shipInfo.size);
Was it helpful?

Solution

If you want to add a function to the 2d context, javascript makes this easy thanks to the prototype inheritance : You can inject the Context2D object to add or change its function as you wish.
You might want to look at a few addings i made to the context in a small canvas lib i made here : https://github.com/gamealchemist/CanvasLib

Some will tell that injecting is evil, but unless you're on a huge boat i would just say : If you use some graphic library, respect the semantic of existing functions and everything should be fine. If you don't use libs : do whatever it takes !

So, to answer more specifically to your question, your shorter drawImage would give :

CanvasRenderingContext2D.prototype.draw_image = function ( image, 
                                                            srcPos, size, 
                                                            dstPos, size) {
      this.drawImage(image, srcPos[0], srcPos[1], size[0], size[1], 
                               dstPos[0], dstPos[1], size[0], size[1]);
}; 

Then you can use the new function on all your contexts :

var canvas = document.getElementById("display"),
     frame  = canvas.getContext("2d");
frame.draw_image( ... ) ;

Notice that you could use 'rect' objects, which would be arrays with 4 elements, x, y, w, h, and lead to an even shorter syntax.

Edit : i see in your lib that you want to rotate your rect.
First thing is that you don't want to reset the transform. Just save it then restore it.
I would try something closer to this :

var x = dstPos[0],
    y = dstPos[1],
    halfWidth = dstSize[0]*0.5, // !! not src use >>1 if you know it's an int.
    halfHeight = dstSize[1]*0.5, // !! not src  ...
    angleInRads = angle * Math.PI / 180;
this.save();
this.translate(x+halfWidth,y+halfHeight);
this.rotate(angleInRads);
this.drawImage(image
                , center[0], center[1], srcSize[0], srcSize[1]
                 , -halfWidth, -halfHeight, dstSize[0],dstSize[1]);
this.restore();

OTHER TIPS

Your small image library would fit well inside a javascript object.

A Demo: http://jsfiddle.net/m1erickson/7pZJw/

enter image description here

A javascript object can hold information about your image:

  • the image itself
  • the image size (can be automatically calculated for you)
  • the image centerpoint (can be automatically calculated for you)

Example:

// create a new object
// fill it with the info about the image

var object={
    image:shipImage,
    width:shipImage.width,
    height:shipImage.height,
    centerOffsetX:shipImage.width/2,
    centerOffsetY:shipImage.height/2,
    radius:35,
    angle:45,
};

A javascript object can also hold functions that draws the image (as you've done in your code)

Example:

// when you call object.draw the image will be drawn by this function
// which is added to the object itself

draw:function(context,atX,atY,newWidth,newHeight){
    context.drawImage(
        this.image,
        0,0,this.width,this.height,
        atX,atY,newWidth,newHeight);
},

A function to create your small image library inside a javascript object might look like this:

function createImageObject(image,radius,angle){

    // create a new object
    // fill it with the info about the image
    var object={
        image:image,
        width:image.width,
        height:image.height,
        centerOffsetX:image.width/2,
        centerOffsetY:image.height/2,
        radius:radius,
        angle:angle,
        draw:function(context,atX,atY,newWidth,newHeight){
            context.drawImage(
                this.image,
                0,0,this.width,this.height,
                atX,atY,newWidth,newHeight);
        },
    };
    return(object);
}

And you can use your ship object library like this:

// create a new ship object

var shipObject=createImageObject(img,35,45);

// draw the ship image using the ship object
// draw at 20,20 with size 75,75

shipObject.draw(frame,20,20,75,75);

BTW, I see you're using the version of drawImage that will scale/clip the source image.

If you just want to draw the full image at its original size you can do this shortcut:

// draw the image full-sized at x,y

context.drawImage(image,x,y);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top