Canvas offset

I am trying to change the origin of the canvas template, but I cannot achieve what I want.

I need to draw a line filled with a dotted line. A dotted pattern is created using createPattern (feed a dynamically created canvas element).

A canvas (essentially a red dot) is created as follows:

 function getPatternCanvas() { var dotWidth = 20, dotDistance = 5, patternCanvas = document.createElement('canvas'), patternCtx = patternCanvas.getContext('2d'); patternCanvas.width = patternCanvas.height = dotWidth + dotDistance; // attempt #1: // patternCtx.translate(10, 10); patternCtx.fillStyle = 'red'; patternCtx.beginPath(); patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); patternCtx.closePath(); patternCtx.fill(); return patternCanvas; } 

Then the line is drawn using this template (canvas):

 var canvasEl = document.getElementById('c'); var ctx = canvasEl.getContext('2d'); var pattern = ctx.createPattern(getPatternCanvas(), 'repeat'); // attempt #2 // ctx.translate(10, 10); ctx.strokeStyle = pattern; ctx.lineWidth = 30; ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(100, 100); ctx.stroke(); 

So we get the following:

enter image description here

Now I would like to compensate for the origin of these points by, say, 10 pixels. Moving the template canvas does not help, since we do not get the full points:

enter image description here

And translating the context of the canvas itself does not help, because it shifts the line, not the template itself:

enter image description here

The transfer context does not seem to affect the origin of the template.

Is there a way to change the offset of the template itself?

+6
source share
2 answers

Update . Since this answer was posted, now (starting from 2015/02) there is a local setTransform() in the CanvasPattern instance CanvasPattern (see specifications ). It may not be available in all browsers (only Firefox supports it when it was written).

Method 1

You can compensate for the main canvas and add the delta value to the actual position of the line:

 var offsetX = 10, offsetY = 10; ctx.translate(offsetX, offsetY); ctx.lineTo(x - offsetX, y - offsetY); // ... 

Example

(The demo only shows the transformed pattern, but of course you usually move the line along with it).

Line

etc .. so you cancel the transfer for the line itself. But it introduces some overhead, since the coordinates must be calculated every time if you can not cache the resulting value.

Method 2

Another way I can think of is to create a sample template. That is, for the canvas of the template, repeat the point so that when you move it beyond its border, it repeats in the opposite direction.

For example, the first square is a normal template, the second is an offset template described as method two, and the third image uses an offset template to fill, indicating that it will work.

The key is that the two patterns are the same size and the first pattern is repeated in this second version. The second version can be used as a fill on the main one.

Example 2

Animated Example 3

Dots

 var ctx = demo.getContext('2d'), pattern; // create the pattern ctx.fillStyle = 'red'; ctx.arc(25, 25, 22, 0, 2*Math.PI); ctx.fill(); // offset and repeat first pattern to base for second pattern ctx = demo2.getContext('2d'); pattern = ctx.createPattern(demo, 'repeat'); ctx.translate(25, 25); ctx.fillStyle = pattern; ctx.fillRect(-25, -25, 50, 50); // use second pattern to fill main canvas ctx = demo3.getContext('2d'); pattern = ctx.createPattern(demo2, 'repeat'); ctx.fillStyle = pattern; ctx.fillRect(0, 0, 200, 200); 
+10
source

You can simply translate the context after drawing a line / shape and before stroking / filling to offset the pattern. Updated fiddle http://jsfiddle.net/28BSH/27/

 ctx.fillStyle = somePattern; ctx.beginPath(); ctx.moveTo(20, 20); ctx.lineTo(180, 180); ctx.save(); ctx.translate(offset, offset); ctx.stroke(); ctx.restore(); 
+4
source

Source: https://habr.com/ru/post/958963/


All Articles