RoughPath
See SVG path.
const path = new RoughPath({
d: 'M 100 100 L 200 200 L 300 100 Z',
stroke: 'red',
strokeWidth: 10,
fill: 'blue',
});
$icCanvas = call(() => {
return document.createElement('ic-canvas');
});
path = call(() => {
const { Canvas, RoughPath } = Core;
const path = new RoughPath({
d: 'M 100 100 L 200 200 L 300 100 Z',
stroke: 'red',
strokeWidth: 10,
fill: 'blue',
});
path.position.x = 250;
return path;
});
call(() => {
const { Canvas } = Core;
const gui = new GUI({
container: $icCanvas.parentElement,
});
const config = {
strokeLinecap: 'butt',
strokeLinejoin: 'miter',
strokeMiterlimit: 4,
strokeDasharray: 0,
strokeDashoffset: 0,
strokeAlignment: 'center',
stroke: '#ff0000',
strokeWidth: 10,
strokeOpacity: 1,
fill: '#0000ff',
};
gui.add(config, 'strokeAlignment', ['center', 'inner', 'outer']).onChange(
(strokeAlignment) => {
path.strokeAlignment = strokeAlignment;
},
);
gui.add(config, 'strokeLinecap', ['butt', 'square', 'round']).onChange(
(strokeLinecap) => {
path.strokeLinecap = strokeLinecap;
},
);
gui.add(config, 'strokeLinejoin', ['miter', 'bevel', 'round']).onChange(
(strokeLinejoin) => {
path.strokeLinejoin = strokeLinejoin;
},
);
gui.add(config, 'strokeMiterlimit', 0, 10, 0.5).onChange(
(strokeMiterlimit) => {
path.strokeMiterlimit = strokeMiterlimit;
},
);
gui.add(config, 'strokeDasharray', 0, 20, 1).onChange((strokeDasharray) => {
path.strokeDasharray = [strokeDasharray, strokeDasharray];
});
gui.add(config, 'strokeDashoffset', 0, 50, 1).onChange(
(strokeDashoffset) => {
path.strokeDashoffset = strokeDashoffset;
},
);
gui.addColor(config, 'stroke').onChange((stroke) => {
path.stroke = stroke;
});
gui.add(config, 'strokeWidth', 0, 20, 1).onChange((strokeWidth) => {
path.strokeWidth = strokeWidth;
});
gui.add(config, 'strokeOpacity', 0, 1, 0.1).onChange((strokeOpacity) => {
path.strokeOpacity = strokeOpacity;
});
gui.addColor(config, 'fill').onChange((fill) => {
path.fill = fill;
});
$icCanvas.parentElement.style.position = 'relative';
$icCanvas.addEventListener('ic-ready', (e) => {
const canvas = e.detail;
canvas.appendChild(path);
});
});
d
Refer to SVG d attribute, which is a string containing a sequence of path commands that define the path to be drawn.
tessellationMethod
Tessellation method, default value is TesselationMethod.EARCUT
.
export enum TesselationMethod {
EARCUT,
LIBTESS,
}
While TesselationMethod.LIBTESS
has lower performance, it provides better accuracy. See Lesson 013 for details.
fillRule
The SVG fill-rule determines the fill area of the Path, with a default value of "nonzero"
.
type CanvasFillRule = 'evenodd' | 'nonzero';
In the example below, the left side uses nonzero
and the right side uses evenodd
. Additionally, since earcut doesn't support self-intersecting paths, we use TesselationMethod.LIBTESS
for path triangulation.
How to Define Holes
In SVG, holes can be defined by using the opposite winding direction compared to the outline. For example, in the path below, the outline is clockwise M0 0 L100 0 L100 100 L0 100 Z
, while the two subsequent holes are counterclockwise:
M0 0 L100 0 L100 100 L0 100 Z M50 50 L50 75 L75 75 L75 50 Z M25 25 L25
Alternatively, the winding direction can be reversed, such as in Draw a hollow circle in SVG, as long as the winding direction of the hole is opposite to that of the outline.