Skip to content Skip to sidebar Skip to footer

Globalcompositeoperation And Concentric, Hollow, Moving Shapes

I'm trying to achieve the following: A number of concentric circles (or rings) are drawn on a canvas. Each circle has a 'hole' in it, so the smaller circles, drawn behind it are pa

Solution 1:

I would not try to use globalCompositeOperation, since i find it hard to figure out what will happen after several iterations, and even harder if the canvas was not cleared before.

I prefer to use clipping, which gets me to that :

http://jsbin.com/guzubeze/1/edit?js,output

enter image description here

So, to build a 'hole' in a draw, how to use clipping ? -->> Define a positive clipping sub-path, and within this area, cut off a negative part, using this time a clockwise sub-path :

enter image description here

Clipping must be done with one single path, so rect() cannot be used : it does begin a path each time, and does not allow to choose clockwisity (:-)), so you have to define those two functions which will just create the desired sub-paths :

// clockwise sub-path of a rect
function rectPath(x,y,w,h) {
  ctx.moveTo(x,y);
  ctx.lineTo(x+w,y);
  ctx.lineTo(x+w,y+h);
  ctx.lineTo(x,y+h);
}

// counter-clockwise sub-path of a rect
function revRectPath(x,y,w,h) {
  ctx.moveTo(x,y);
  ctx.lineTo(x,y+h);
  ctx.lineTo(x+w,y+h);
  ctx.lineTo(x+w,y);  
}

then you can write your drawing code :

functiondrawShape(cx, cy, d, scale, rotation) {
  ctx.save();
  ctx.translate(cx,cy);
  scale = scale || 1;
  if (scale !=1) ctx.scale(scale, scale);
  rotation = rotation || 0;
  if (rotation) ctx.rotate(rotation);
  // clip with rectangular hole
  ctx.beginPath();
  var r=d/2; 
  rectPath(-r,-r, d, d);
  revRectPath(-0.25*r,-0.8*r, 0.5*r, 1.6*r);
  ctx.closePath();
  ctx.clip();
  ctx.beginPath();
  // we're clipped !
  ctx.arc(0,0, r, 0, 2*Math.PI);
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

Edit :

For the record, there is a simpler way to draw the asked scheme : just draw a circle, then draw counter clockwise a rect within. What you fill will be the part inside the circle that is outside the rect, which is what you want :

function drawTheThing(x,y,r) {
   ctx.beginPath();
   ctx.arc(x ,y, r, 0, 2*Math.PI);
   revRectPath(x-0.25*r, y-0.8*r, 0.5*r, 1.6*r);
   ctx.fill();
   ctx.closePath();
}

(i do not post image : it is the same).

Depending on your need if you change the draw or if you want to introduce some kind of genericity, use first or second one. If you do not change the scheme later, the second solution is simpler => better.

Post a Comment for "Globalcompositeoperation And Concentric, Hollow, Moving Shapes"