Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set allowed drawing area in JavaScript canvas API

I'm using the JavaScript canvas API for free drawing. I'm stuck at masking the area that is allowed to be drawn on - in my example it should only be the speechbubble area. I'm using this Vue component: https://github.com/sametaylak/vue-draw/blob/master/src/components/CanvasDraw.vue

draw(event) {
  this.drawCursor(event);
  if (!this.isDrawing) return;
  if (this.tools[this.selectedToolIdx].name === 'Eraser') {
    this.canvasContext.globalCompositeOperation = 'destination-out';
  } else {
    this.canvasContext.globalCompositeOperation = 'source-over';
    this.canvasContext.strokeStyle = this.tools[this.selectedToolIdx].color;
  }
  this.canvasContext.beginPath();
  this.canvasContext.moveTo(this.lastX, this.lastY);
  this.canvasContext.lineTo(event.offsetX, event.offsetY);
  this.canvasContext.stroke();
  [this.lastX, this.lastY] = [event.offsetX, event.offsetY];
},
drawCursor(event) {
  this.cursorContext.beginPath();
  this.cursorContext.ellipse(
    event.offsetX, event.offsetY,
    this.brushSize, this.brushSize,
    Math.PI / 4, 0, 2 * Math.PI
  );
  this.cursorContext.stroke();
  setTimeout(() => {
    this.cursorContext.clearRect(0, 0, this.width, this.height);
  }, 100);
},

like image 989
Tom Avatar asked Aug 28 '26 23:08

Tom


1 Answers

There is a built-in clip() method which sets a path as the clipping region.

var ctx=document.getElementById("cnv").getContext("2d");
ctx.lineWidth=2;

ctx.strokeStyle="red";
ctx.moveTo(0,0);
ctx.lineTo(100,100);
ctx.stroke();                // 1.

ctx.strokeStyle="black";
ctx.beginPath();
ctx.moveTo(10,10);
ctx.lineTo(100,10);
ctx.lineTo(100,60);
ctx.lineTo(30,60);
ctx.lineTo(10,80);
ctx.closePath();
ctx.stroke();                // 2.
ctx.clip();                  // 3.

ctx.strokeStyle="green";
ctx.beginPath();
ctx.moveTo(0,100);
ctx.lineTo(100,0);
ctx.stroke();                // 4.
<canvas id="cnv"></canvas>
  1. red line is drawn between 0,0 and 100,100, without clipping
  2. bubble is drawn in black
  3. bubble is set as clipping region
  4. green line is drawn between 0,100 and 100,0, and correctly clipped into the bubble.

In practice you may want to have the clipping region one pixel inside the bubble, so a separate path (which is not stroke()-d, just clip()-ped), so drawing can not modify the bubble itself. If you zoom in now as it is, you will see that the green line actually overdraws the inner pixels of the bubble (linewidth is 2 pixels, and the outer one is "unharmed").

like image 151
tevemadar Avatar answered Aug 30 '26 13:08

tevemadar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!