Using FabricJS, is there a way to not select an object when clicking its negative space? Assume the object is a dynamically drawn not-rectangle shape, like a star.
Alternative; works: For reference, apparently the Konva drawing library has this ability by default. Here's a Konva setup in codepen, with star shapes, showing negative-space not-clickable: https://codepen.io/MarsAndBack/pen/zYmRReE?editors=1111
Codepen: https://codepen.io/MarsAndBack/pen/MWPQQVe?editors=1111
const canvasEl = document.getElementById("canvas")
var canvas, object_star
init()
drawObjects()
function init() {
canvas = new fabric.Canvas(canvasEl)
let width = document.getElementById("canvasWrapper").clientWidth
let height = document.getElementById("canvasWrapper").clientHeight
canvas.setWidth(width)
canvas.setHeight(height)
}
function drawObjects() {
let points = starPolygonPoints(5,50,25)
object_star = new fabric.Polygon(points, {
stroke: 'black',
fill: 'yellow',
left: 50,
top: 50,
strokeWidth: 4,
strokeLineJoin: 'bevil'
}, false)
canvas.add(object_star)
}
function starPolygonPoints(spikeCount, outerRadius, innerRadius) {
var rot = Math.PI / 2 * 3
var cx = outerRadius
var cy = outerRadius
var sweep = Math.PI / spikeCount
var points = []
var angle = 0
for (var i = 0; i < spikeCount; i++) {
var x = cx + Math.cos(angle) * outerRadius
var y = cy + Math.sin(angle) * outerRadius
points.push({x: x, y: y})
angle += sweep
x = cx + Math.cos(angle) * innerRadius
y = cy + Math.sin(angle) * innerRadius
points.push({x: x, y: y})
angle += sweep
}
return (points)
}
#canvasWrapper {
width: 100%;
height: 100%;
}
#canvas {
background-color: pink;
}
<script src="https://cdn.jsdelivr.net/npm/fabric"></script>
<div id="canvasWrapper">
<canvas id="canvas" width="400" height="400"></canvas>
</div>
Took way longer than expected to find this (with help from others too)!
FabricJS has two properties relevant to this:
perPixelTargetFind
: Boolean - "When true, object detection happens on per-pixel basis rather than on per-bounding-box" http://fabricjs.com/docs/fabric.Canvas.html#perPixelTargetFind
targetFindTolerance
: Number - "Number of pixels around target pixel to tolerate (consider active) during object detection"
http://fabricjs.com/docs/fabric.Canvas.html#targetFindTolerance
Apply them to the entire scene:
canvas = new fabric.Canvas(canvasElement, {
// ...
perPixelTargetFind:true,
targetFindTolerance: 15
// ...
})
or per-object:
line = new fabric.Line(points, {
// ...
perPixelTargetFind: true,
targetFindTolerance: 10
// ...
})