Resize image proportionately to fit into HTML5 canvas

watzon picture watzon · Oct 12, 2011 · Viewed 9.4k times · Source

I am trying to write a jQuery plugin that will have similar functionality to the Flash based product editor on Zazzle.com. What I need to know is how, using the context.drawImage() canvas function, I can insert an image and resize it to fit in the canvas without distorting it.

The image is 500x500px and so is the canvas, but for some reason when I set 500x500 to the image dimentions it is way to big.

Here is my full code so far:

(function( $ ) {

    jQuery.fn.productEditor = function( options ) {

        var defaults = {
            'id'        :   'productEditor',
            'width'     :   '500px',
            'height'    :   '500px',
            'bgImage'   :   'http://www.wattzup.com/projects/jQuery-product-editor/sampleProduct.jpg'
        };


        return this.each(function() {

            var $this = $(this)

                var options = $.extend( defaults, options );

            // Create canvas
            var canvas = document.createElement('canvas');

            // Check if their browser supports the canvas element
            if(canvas.getContext) {
                // Canvas defaults
                    var context = canvas.getContext('2d');
                    var bgImage = new Image();
                    bgImage.src = options.bgImage;
                    bgImage.onload = function () {          
                    // Draw the image on the canvas
                    context.drawImage(bgImage, 0, 0, options.width, options.height);
                }

                // Add the canvas to our element
                $this.append(canvas);
                // Set ID of canvas
                $(canvas).attr('id', options.id).css({ width: options.width, height: options.height });




            }
            // If canvas is not supported show an image that says so
            else {

                alert('Canvas not supported!');


            }


        });

    };
})( jQuery );

Any other constructive criticism also welcomed.

Answer

Simon Sarris picture Simon Sarris · Oct 12, 2011

This is the problem:

$(canvas).attr('id', options.id).css({ width: options.width, height: options.height });

You are setting the CSS width/height of the canvas when you need to be setting the width and height attributes directly. You are not distorting the image drawn, you are distorting the canvas itself. The canvas is still 300x150 (the default) and has merely been CSS-stretched to be 500x500. Thus right now you are drawing a 500x500 image on a 300x150 stretched canvas!

You need to do:

    var defaults = {
        'id'        :   'productEditor',
        'width'     :   '500',  // NOT 500px, just 500
        'height'    :   '500',  // NOT 500px, just 500
        'bgImage'   :   'http://www.wattzup.com/projects/jQuery-product-editor/sampleProduct.jpg'
    };

...

// Create canvas
var canvas = document.createElement('canvas');
canvas.width = options.width;
canvas.height= options.height;

...

$(canvas).attr('id', options.id); // DON'T change CSS width/height

Note that changing the width or height of a canvas clears it so this MUST be done before using drawImage.