Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize an image with javascript for use inside a canvas createPattern

I've seen a few tricks on how you resize an image you want to use inside an IMG-tag but I want to have an image variable inside a Javascript, resize it and then use the image inside a context.createPattern(image, "repeat"). I have not found any hint on how to do that.

You can find a functional demo at http://karllarsson.batcave.net/moon.html with images on what I want to do.

The solution from Loktar looks good. I haven't had the time yet to fix the correct aspect but now I know how to do it. Thank you once again. Here is an working demo http://karllarsson.batcave.net/moon2.html

This is the two lines I don't get to work as I want them too.

image.width = side * 2;
image.height = side * 2;

function drawShape() {
    try {
        var canvas = document.getElementById('tutorial');                 
        var image = new Image();                                          
        image.src = "http://xxx.yyy.zzz/jjj.jpg";                         
        image.width = side * 2;                                           
        image.height = side * 2;                                          

        if (canvas.getContext){
            var ctx = canvas.getContext('2d');                            
            ctx.clearRect(0, 0, canvas.width, canvas.height);             
            ctx.fillStyle = ctx.createPattern(image, "repeat");           
            ctx.beginPath();                                              
            var centerX = canvas.width / 2 - side / 2;                    
            var centerY = canvas.height / 2 - side / 2;                   
            ctx.rect(centerX, centerY, side, side);                       
            ctx.fill();                                                   
        } else {
            alert('You need Safari or Firefox 1.5+ to see this demo.');   
        }
    } catch (err) {
        console.log(err);                                                 
    }
}
like image 956
user1916806 Avatar asked Dec 19 '12 20:12

user1916806


2 Answers

What you can do is make a temporary canvas, and copy the image to it with the dimensions you require, and then use that temporary canvas as the pattern rather than the image itself.

Live Demo

First create the canvas

          var tempCanvas = document.createElement("canvas"),
              tCtx = tempCanvas.getContext("2d");

          tempCanvas.width = side*2;
          tempCanvas.height = side*2;

Now draw the image to it, making the the scaled size you require

          tCtx.drawImage(image,0,0,image.width,image.height,0,0,side*2,side*2);

And now use the canvas you just created as the pattern

          ctx.fillStyle = ctx.createPattern(tempCanvas, "repeat");

Full code

edit created a more generic reusable example

 function drawPattern(img, size) {
     var canvas = document.getElementById('canvas');

     canvas.height = 500;
     canvas.width = 500;

     var tempCanvas = document.createElement("canvas"),
         tCtx = tempCanvas.getContext("2d");

     tempCanvas.width = size;
     tempCanvas.height = size;
     tCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, size, size);

     // use getContext to use the canvas for drawing
     var ctx = canvas.getContext('2d');
     ctx.clearRect(0, 0, canvas.width, canvas.height);
     ctx.fillStyle = ctx.createPattern(tempCanvas, 'repeat');

     ctx.beginPath();
     ctx.rect(0,0,canvas.width,canvas.height);
     ctx.fill();

}

var img = new Image();
img.src = "http://static6.depositphotos.com/1070439/567/v/450/dep_5679549-Moon-Surface-seamless.jpg";
img.onload = function(){
    drawPattern(this, 100);
}
like image 145
Loktar Avatar answered Sep 20 '22 15:09

Loktar


There is another way, which worked great for me:

const ctx: CanvasRenderingContext2D;
const patternAsBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRjIyRTA3RDgyNkUxMUU5ODQ1QUM2QjE5RUMzRTMwRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRjIyRTA3RTgyNkUxMUU5ODQ1QUM2QjE5RUMzRTMwRCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZGMjJFMDdCODI2RTExRTk4NDVBQzZCMTlFQzNFMzBEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZGMjJFMDdDODI2RTExRTk4NDVBQzZCMTlFQzNFMzBEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+y2y13AAAAV1JREFUeNqc0kFLAkEUB/B9b1ZR1m4FQZeocx2MYI3CxC8QmVBfJAjqVLQQfY/MFI+dREpQIeqQxwgiCrq72661M9Nb0ZKo3dU5zOU//Hj/3Qep04YUn04Ludxq7mdflYCzfFKbprdnLKatc9u8Z1zZbBxkHwc58q79gpGYLgBKqaPqTBB4s5t5Ewx2XNu8YvHEImeysnJYnf8GoyCz/MO+ZXFN56iUw6JSxW333SJ0YoEzpbJq1Oe8DLxLN2qzQoqSGkss8a41Un1wZUGNa2mq346A3IBB6KGSUOahdqeFEsZAO20YDnXjktDomKgoUMM0/A6HJ3UJZSNOCn+FPVSIMv3FpOuYTSaUfGj0v/AH1ZLcsZoYEgW/sF+/TPUJNUOh6Be29jJPAJijlbgjNEV7ehG0p6CEOIP62K/v900xXyyyILA3KWJO2FbgpPj8MHm+dnw9FRp1/Ot/CTAAd/XmF3ta0fUAAAAASUVORK5CYII=';
const imagePattern = new Image();
imagePattern.onload = () => {
    const pattern: CanvasPattern = ctx.createPattern(imagePattern, 'repeat-y');
    const svgMatrix: SVGMatrix = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix();

    svgMatrix.scale(0.5);
    pattern.setTransform(svgMatrix);
}
imagePattern.src = patternAsBase64;

Basically the same as setting the transform matrix to this (the following down under) (But attention! patterns setTransform method awaits a SVGMatrix. This did still work for me, too in Chrome (But TypeScript complained of course):

pattern.setTransform({
    a: 0.5, // Horizontal scaling. A value of 1 results in no scaling.
    b: 0,   // Vertical skewing.
    c: 0,   // Horizontal skewing.
    d: 0.5, // Vertical scaling. A value of 1 results in no scaling.
    e: 0,   // Horizontal translation (moving).
    f: 0    // Vertical translation (moving).
    // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform
});

Keep in mind, that you also maybe need to translate your canvas before drawing the pattern, otherwise it could not start where you want it to start to.

const offset_x: number = positionXOfElement;
const offset_y: number = positionYOfElement;

// offset
ctx.translate(offset_x, offset_y);

// draw
ctx.fillStyle = pattern;
roundRect.fill();
//ctx.fillRect(0, 0, 300, 300);

// undo offset
ctx.translate(-offset_x, -offset_y);
like image 37
Stefan Rein Avatar answered Sep 18 '22 15:09

Stefan Rein