First, I get the svg file and add svg <path>
elements to Konva layer separately using fabric.js (If you know a better way please share).
fabric.loadSVGFromURL(svgFile, (objects) => {
objects.forEach(obj => {
const path = new Konva.Path({
...obj,
data: obj.d,
opacity: 1,
x: 0,
y: 0,
fill: 'white',
globalCompositeOperation: 'destination-over'
})
layer.add(path)
})
})
Then, I added 3 listeners to Konva stage:
mousedown touchstart
mouseup touchend
mousemove touchmove
mousedown touchstart
listener clips context
to a Path2D
which is created with the event target’s path data (data of the element which the mouse pointer was clicked on it) :
stage.on('mousedown touchstart', (event) => {
isDrawing = true
lastPointerPosition = stage.getPointerPosition()
context.save()
const path2d = new Path2D(event.target.attrs.data)
context.clip(path2d)
})
mouseup touchend
listener restores canvas in order to remove clipping.
stage.on('mouseup touchend', () => {
isDrawing = false
context.restore()
})
mousemove touchmove
listener draws on canvas (like a brush):
stage.on('mousemove touchmove', (event) => {
if (!isDrawing) return
const pos = stage.getPointerPosition()
const localPos = {
x: lastPointerPosition.x - image.x(),
y: lastPointerPosition.y - image.y()
}
context.beginPath()
context.moveTo(localPos.x, localPos.y)
localPos = {
x: pos.x - image.x(),
y: pos.y - image.y()
}
context.lineTo(localPos.x, localPos.y)
context.closePath()
context.stroke()
lastPointerPosition = pos
layer.batchDraw()
})
image
is the a Konva.Image which contains the canvas
.
const image = new Konva.Image({
image: canvas,
x: 0,
y: 0
})
layer.add(image)
I got the drawing functionality from Konva demo.
Clipping works fine, except when there is an object below another object, and drawing on the object below overlaps the object above. Here is an example:
So if the mouse was clicked on the circle first, drawing should not overlap the star object:
Thanks for your time, I appreciate your help.