Search code examples
javascriptcanvasfabricjs

How to select only the stroke in a transparent backgroud rectangle?


How can i make a transparent rectangle selectable only when i click on the stroke? I tried two different approach as you can see from the snippet below, the object on the left is a rectangle with a transparent background, the object on the right is a group object with multiple lines. I want to know how to be able to select the element only when i click on the stroke, with both objects if you click on the inner transparent area the object becomes selected.

var canvas = new fabric.Canvas('a');
canvas.add(new fabric.Rect({
  left: 10,
  top: 20,
  height: 160,
  width: 80,
  fill: 'transparent',
  stroke: 'red'
}));
var rectLine1 = new fabric.Line([0, 0, 80, 0], {
  stroke: 'red',
  left: 100,
  top: 20
});
var rectLine2 = new fabric.Line([0, 160, 0, 0], {
  stroke: 'red',
  left: 100,
  top: 20
});
var rectLine3 = new fabric.Line([0, 160, 0, 0], {
  stroke: 'red',
  left: 180,
  top: 20
});
let rectLine4 = new fabric.Line([0, 0, 80, 0], {
  stroke: 'red',
  left: 100,
  top: 180
});
var group = new fabric.Group([rectLine1, rectLine2, rectLine3, rectLine4], {
  left: 110,
  top: 20
})
canvas.add(group)
canvas.renderAll();
.c {
  border: 2px solid black;
}
<script
  src="https://code.jquery.com/jquery-2.2.4.min.js"
  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<canvas id="a" class="c" width="200" height="200"></canvas>


Solution

  • I found that setting perPixelTargetFind: true solves the problem, you can also set a tolerance on the canvas targetFindTolerance: 10 to be able to select objects with thin strokes. I'll paste the working code below in case anyone needs it.

    var canvas = new fabric.Canvas('a', {
      targetFindTolerance: 10
    });
    canvas.add(new fabric.Rect({
      left: 10,
      top: 20,
      height: 160,
      width: 80,
      fill: 'transparent',
      stroke: 'red',
      perPixelTargetFind: true,
    }));
    canvas.renderAll();
    .c {
      border: 2px solid black;
    }
    <script
      src="https://code.jquery.com/jquery-2.2.4.min.js"
      integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
      crossorigin="anonymous"></script>
    <script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
    <canvas id="a" class="c" width="200" height="200"></canvas>