I'm making a painting app, and using the canvas path as a brush:
function onMove(){
ctx.beginPath();
ctx.moveTo(pos.x, pos.y); // from position
pos=getPosition(event);
ctx.lineTo(pos.x, pos.y); // to position
ctx.stroke(); // draw it!
}
I'm stuck between in a dilemma, if I join all the paths into one I lose intersection overlap, and if I draw them real time separately I get those start/end overlaps spheres.
Is there a clean way I can solve this problem? Thank you.
Okey, then it is getting complicated since we are dealing with alpha values here..
Basicly you can draw the "missing part" of the new line in a buffer canvas by using destination-in
and source-in
blend modes.
The idea is: to "compute" the overlapp of the N-1 the Nth line and then only draw line N outside this overlap: (for demonstation the Nth line will be drawn in red.)
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const canvas2 = document.createElement('canvas')
canvas2.width = 300
canvas2.height = 300
const ctx2 = canvas2.getContext('2d');
ctx.lineWidth = 30
ctx.lineCap = 'round';
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
ctx.imageSmoothingEnabled = false;
ctx.lineJoin = "round"
function drawLine1(ctx) {
ctx.beginPath();
ctx.moveTo(250, 250);
ctx.lineTo(100, 250);
ctx.stroke();
}
function drawLine2(ctx) {
ctx.beginPath();
ctx.moveTo(100, 250);
ctx.lineTo(100, 50);
ctx.stroke();
}
// draw image until line n-1 on screen
ctx.beginPath();
ctx.moveTo(0, 100);
ctx.lineTo(250, 100); // 1st
ctx.lineTo(250, 250); // 2nd
ctx.lineTo(100, 250); // n-1
ctx.stroke();
// clear buffer canvas and setup
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.lineWidth = 30
ctx2.lineCap = 'round';
ctx2.imageSmoothingEnabled = false;
// draw line n-1 on buffer in opaque color
ctx2.strokeStyle = 'rgba(0,0,0,1)';
drawLine1(ctx2)
// draw line n on buffer in "destination-in" blend mode opaque
ctx2.globalCompositeOperation = 'destination-in';
ctx2.strokeStyle = 'rgba(0,0,0,1)';
drawLine2(ctx2)
// draw line n on buffer in "source-out" blend mode and original color
ctx2.globalCompositeOperation = 'source-out';
ctx2.strokeStyle = 'rgba(255,0,0,0.5)';
drawLine2(ctx2)
ctx.drawImage(canvas2, 0 ,0)
<canvas id="canvas" width="400" height="400"></canvas>
It is not perfect, but it is a starting point..