Interpolate stroke width between points in Paper.js - javascript

I am using Paper.js to create some shapes. It has worked great so far. One thing where I am stuck is variable stroke width. I want to stroke width to change between different points just like the color changes in gradients. Here is some code:
var firstSegment = new Segment({
point: [100, 50],
handleOut: [80, 100]
});
var secondSegment = new Segment({
point: [300, 50],
handleIn: [-80, -100]
});
var path = new Path({
segments: [firstSegment, secondSegment],
strokeColor: 'black',
strokeWidth: 4
});
In the above example, the strokeWidth is 4 everywhere along the path. How can I create a path such that it starts with a stroke width of 1px and then gets 6px wide at the other end?

Related

Konva.js dotted stroke around Img element with text

I'm new to Konva.js lib, I implemented drag and drop of the img inside the canvas element, I would like to point user that the img is draggable so I would like to do something like this ->
Any Ideas how to do this inside Konva.js ? Thanks!
You can use stroke with the combination of dash property to make a dotted stroke
Konva.Image.fromURL('https://i.imgur.com/ktWThtZ.png', img => {
img.setAttrs({
x: 50,
y: 50,
scaleX: 0.5,
scaleY: 0.5,
stroke: 'red',
strokeWidth: 10,
dash: [10, 10],
draggable: true
});
layer.add(img);
layer.draw();
});
Demo: https://jsbin.com/xoporixura/1/edit?html,js,output
If you need padding for the stroke you can add a rectangle on top of the image with the bigger size.

Parallel lines separator in Konva

I'm trying to draw a separator with 2 lines for my road. I already tried to make it with just 2 parallels lines, but when I made my road curve, it doesn't look very good. Like this:
Small curve:
Big curve:
Because of it now I am just drawing one line with white background behind the line with black background. But sometimes my main road is not black. How can I make space between these lines transparent?
Examples:
Normal work:
Work with road with different background:
You can drag separator in the example below
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
var line = new Konva.Line({
points: [100, 100, 200, 200],
strokeWidth: 100,
stroke: 'black',
draggable: true,
});
var line_2 = new Konva.Line({
points: [400, 100, 500, 200],
strokeWidth: 100,
stroke: 'red',
draggable: true,
});
const group_sep = new Konva.Group({
draggable: true,
});
var sep_1 = new Konva.Line({
points: [100, 100, 200, 200],
strokeWidth: 20,
stroke: 'green',
});
var sep_2 = new Konva.Line({
points: [100, 100, 200, 200],
strokeWidth: 10,
stroke: '#000000',
});
group_sep.add(sep_1);
group_sep.add(sep_2);
layer.add(line);
layer.add(line_2);
layer.add(group_sep);
stage.add(layer);
layer.draw();
<script src="https://unpkg.com/konva#4.0.16/konva.min.js"></script>
<div id="container"></div>
You can use blend mode via globalCompositeOperation to "cut" one line from another.
const group_sep = new Konva.Group({
draggable: true,
});
var sep_1 = new Konva.Line({
points: [100, 100, 200, 200],
strokeWidth: 20,
stroke: 'green',
});
// destination-out will cut line from previous drawings
var sep_2 = new Konva.Line({
points: [100, 100, 200, 200],
strokeWidth: 10,
stroke: '#000000',
globalCompositeOperation: 'destination-out'
});
But you should know that destination-out will cut your line from ALL previous drawings on the canvas. It means it may cut the background too. To fix the issues you can move your group with the lines into another Konva.Layer or just cache the group:
group_sep.cache();
Note: remember to recache to group every time you change the lines.
Demo: https://jsbin.com/ravodomigi/3/edit?html,js,output

Fabric.js specify lineCap style

In html5 canvas it is possible to specify lineCap style for the line ends.
E.g.:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineCap="round"; // <-- here lineCap is specified
ctx.moveTo(20,20);
ctx.lineTo(200,20);
Possible options are: butt (Default), round, square.
My question is:
How to specify lineCap style when creating the Line with fabric.js?
var line = new fabric.Line(
[0, 100, 200, 100],
{
strokeWidth: 5
// I presume some option should be specified here, but how is it should be called?
}
);
I found an answer
Posting it here, as it is not obvious from the fabric.js documentation:
var line = new fabric.Line(
[0, 100, 200, 100],
{
strokeWidth: 5,
strokeLineCap: "round" // <-- this makes 'round' line ends style
}
);

Paper.js - Clipping opacity for paths outside of area

I have a simple rectangle that forms the clipping area for all shapes added to the canvas, which is working great:
var area = new paper.Rectangle(
100, 100, 300, 120
);
var path = new paper.Path.Rectangle(area);
group.addChild(path);
group.clipped = true;
What I'm trying to achieve is instead of hiding the paths that fall outside of this area, they are shown with a slight opacity, something like:
Thanks in advance for any help and suggestions.
This is not a simple way as clipped, you might do it by using method intersect.
Please try this code.
// SET INITIAL
var area = new paper.Path.Rectangle(100, 100, 300, 220);
area.fillColor = 'yellow'
area.opacity = 0.2
var circle1 = new paper.Path.Circle({
center:[150, 150],
radius: 100,
fillColor: 'red'
})
// OPACITY CLIPPING
var circle2 = circle1.intersect(area)
circle1.opacity = 0.2

Implementing an eraser with paperjs

I've checked, similar questions have been asked, but have been left partially answered or not answered at all.
I need to build an eraser tool with PaperJS that will be able to erase existing paths, without erasing the image underneath.
So the image can reside on the first layer, and the paths on the second. See the accompanying JSFiddle: jsfiddle which shows two attempts:
paper.install(window);
var canvas = document.getElementById("myCanvas");
paper.setup(canvas);
//the yellow background (can also be background image) which should NOT be erased
var rect = new Rectangle(new Point(0, 0), new Point(paper.view.size.width, paper.view.size.height));
var rectPath = new Path.Rectangle(rect);
rectPath.fillColor = 'yellow';
//first attempt to erase the black line
var first = paper.project.activeLayer;
var second = new Layer();
var from = new Point(50, 0);
var to = new Point(50, 100);
var path1 = new Path.Line(from, to);
path1.strokeColor = 'black';
path1.strokeWidth = 40;
var from = new Point(0, 50);
var to = new Point(100, 50);
var path2 = new Path.Line(from, to);
path2.strokeColor = 'green'; //I've tried other colors as well, this seems irrelevant
path2.strokeWidth = 40;
path2.blendMode = 'destination-out';
//So I saw this
var path = new CompoundPath({
children: [
new Path.Circle({
center: new Point(200, 50),
radius: 30
}),
new Path.Circle({
center: new Point(200, 50),
radius: 10
})
],
fillColor: 'black',
selected: true
});
//second attempt
//I need to actually erase with one line through lots of paths, not sure how to implement it with this
var path = new CompoundPath({
children: [
new Path.Line({
from: [350, 0],
to: [350, 100],
strokeWidth: 30,
strokeColor: 'green' //irrelevant it seems
}),
new Path.Line({
from: [300, 50],
to: [400, 50],
strokeWidth: 30,
strokeColor: 'white' //irrelevant it seems
})
],
strokeColor: 'black',
selected: true,
strokeWidth: 20
});
paper.view.draw();
<script src="http://tmantechblog.com/testpaperjs/js/libs/paper.js"></script>
<canvas id="myCanvas" height='500' width='500'>This does not support HTML5 canvas</canvas>
The first attempt tries to use blendMode='destination-out' but it leaves a white mark rather than a transparent path
The second implementation tries to mimic the compoundPath example provided there, but where the paths cross, no hole is produced. Also, I'm unsure how this can be used to implement an eraser across multiple paths.
Any advice on how to proceed will be appreciated. Otherwise I'll have to port my whole project either to the basic HTML 5 canvas or FabricJS, or something similar.

Categories

Resources