13

I have a code:

function draw(ctx) {
  // create new image object to use as pattern
  var img = new Image();
  img.onload = function(){
    // create pattern
    var ptrn = ctx.createPattern(img,'repeat');
    ctx.fillStyle = ptrn;
    ctx.fillRect(0,0,150,150);
  }
  img.src = 'images/wallpaper.png?' + new Date().getTime();
}

How can i move the start position of pattern image?

Glebka
  • 1,420
  • 3
  • 20
  • 37

3 Answers3

21

In response to the accepted answer: rather than undo the offset, I would use save() & restore() to avoid potential problems:

ctx.save();
ctx.translate(offset_x, offset_y);
ctx.fillRect(-offset_x, -offset_y, fill_x, fill_y);
ctx.restore();
cacheflowe
  • 759
  • 9
  • 9
  • 3
    `save` and `restore` seems like tidier way to do it. – mokagio Dec 20 '14 at 09:48
  • 2
    For something as trivial as applying a single transformation to the context I would not recommend using `save()` and `restore()`. There is overhead associated with manipulating the state stack (albeit minimal), and if you do this for every simple transformation you'll be taking an unnecessary performance hit. See this jsPerf (which I take no credit for) for a quick comparison: http://jsperf.com/canvas-transform-vs-save-restore/2 – Xenethyl Feb 01 '15 at 17:02
  • A little more than a year later, the perf test above now says that save/restore is faster than re-translating (at least in Firefox & Chrome on OS X). For something this simple, performance concerns shouldn't necessarily trump simplicity & readability. But, as with any code, we all have our personal preferences :) – cacheflowe Mar 11 '16 at 21:20
15

You can achieve this by translating the canvas, drawing on it, and then translating it back to where you started:

function draw(ctx) {
    // create new image object to use as pattern
    var img = new Image();
    img.onload = function(){
        // create pattern
        var ptrn = ctx.createPattern(img,'repeat');
        ctx.fillStyle = ptrn;

        // offset vars
        var offset_x = 60;
        var offset_y = 75;
        var fill_x = 500; // could be canvas.width
        var fill_y = 500; // could be canvas.height

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

        // draw
        ctx.fillRect(-offset_x, -offset_y, fill_x, fill_y);

        // undo offset
        ctx.translate(-offset_x, -offset_y);
    }
    img.src = 'images/wallpaper.png?' + new Date().getTime();
}
Xenethyl
  • 3,179
  • 21
  • 31
  • @GLeBaTi I just edited the code I posted here slightly. The important change is that the call to `fillRect()` only fills a region of the size you request (ie. `fill_x` and `fill_y`) because we pass the origin in as our offset. I also adjusted the signs on the offset used for the translate calls to make the results a bit more intuitive. – Xenethyl Oct 09 '11 at 17:24
1

More general, complex transforms of the pattern alone are easily done. The trick is to do them immediately before the call to fill() or stroke().

function draw(ctx) {
    // create new image object to use as pattern
    var img = new Image();
    img.onload = function(){
        // create pattern
        var ptrn = ctx.createPattern(img,'repeat');
        ctx.fillStyle = ptrn;
        ctx.beginPath();
        ctx.rect(0, 0, 150, 150);

        ctx.translate(-33, -33);
        ctx.fill();
    }

    img.src = 'images/wallpaper.png?' + new Date().getTime();
}
Steve Hanov
  • 11,316
  • 16
  • 62
  • 69