Advanced Drawing with Pixi.js
Stars, bursts, gears, wedges, polygons, arcs, and dashes all drawn using Pixi.js, the HTML5 creation engine with the fastest, most flexible 2D WebGL renderer.
It was many years ago when adding a burst to a graphic I stumbled upon the Funky Monkey drawing script by Ric Ewing. Comments embedded in the function immediately resonated with me:
Burst is a method for drawing star bursts. If you’ve ever worked with an advertising department, you know what they are ;-)
Clients tend to want them, Developers tend to hate them…
Thought I’d bring these back to life leveraging modern web.
Here are seven of those drawing shapes ported to Pixi.js.
Drawing Dashes
Draws a dashed line from point x1, y1 to point x2, y2.
Usage:
target
— Graphics instance on which dashed line will be drawnx1
— Starting position along x-axisy1
— Starting position along y-axisx2
— Final position along x-axisy2
— Final position along y-axisdashLength
— Length of each dash, in pixelsspaceLength
— Space between dashes, in pixels
function drawDash(target,
x1,
y1,
x2,
y2,
dashLength = 5,
spaceLength = 5) {
let x = x2 - x1;
let y = y2 - y1;
let hyp = Math.sqrt((x) * (x) + (y) * (y));
let units = hyp / (dashLength + spaceLength);
let dashSpaceRatio = dashLength / (dashLength + spaceLength);
let dashX = (x / units) * dashSpaceRatio;
let spaceX = (x / units) - dashX;
let dashY = (y / units) * dashSpaceRatio;
let spaceY = (y / units) - dashY; target.moveTo(x1, y1); while (hyp > 0) {
x1 += dashX;
y1 += dashY;
hyp -= dashLength;
if (hyp < 0) {
x1 = x2;
y1 = y2;
}
target.lineTo(x1, y1);
x1 += spaceX;
y1 += spaceY;
target.moveTo(x1, y1);
hyp -= spaceLength;
}
target.moveTo(x2, y2);
}
Drawing Arcs
Draws an arc from starting position x, y.
Usage:
target
— Graphics instance on which dashed line will be drawnx
— X coordinate of the starting pointy
— Y coordinate of the starting pointradius
— Radius of the arcarc
— Sweep of the arc (negative values draw clockwise)startAngle
— Starting offset angle in degreesyRadius
— Y radius of the arc, if different than radius will draw an oval
function drawArc(target,
x,
y,
radius,
arc,
startAngle = 0,
yRadius = 0) {
if (yRadius === 0)
yRadius = radius; let segs = Math.ceil(Math.abs(arc) / 45);
let segAngle = arc / segs;
let theta = -(segAngle / 180) * Math.PI;
let angle = -(startAngle / 180) * Math.PI;
let ax = x - Math.cos(angle) * radius;
let ay = y - Math.sin(angle) * yRadius;
let angleMid, bx, by, cx, cy;
if (segs > 0) {
target.moveTo(x, y);
for (let i = 0; i < segs; ++i) {
angle += theta;
angleMid = angle - (theta / 2);
bx = ax + Math.cos(angle) * radius;
by = ay + Math.sin(angle) * yRadius;
cx = ax + Math.cos(angleMid) * (radius / Math.cos(theta / 2));
cy = ay + Math.sin(angleMid) * (yRadius / Math.cos(theta / 2));
target.quadraticCurveTo(cx, cy, bx, by);
}
}
}
Drawing Wedges
Draws pie shaped wedges, such as in pie charts.
Usage:
target
— Graphics instance on which dashed line will be drawnx
— X coordinate of the center pointy
— Y coordinate of the center pointradius
— Radius of the wedgearc
— Sweep of the arc (negative values draw clockwise)startAngle
— Starting angle in degreesyRadius
— Y radius of the wedge
function drawWedge(target,
x,
y,
radius,
arc,
startAngle = 0,
yRadius = 0) {
let segs = Math.ceil(Math.abs(arc) / 45);
let segAngle = arc / segs;
let theta = -(segAngle / 180) * Math.PI;
let angle = -(startAngle / 180) * Math.PI;
let ax = x + Math.cos(startAngle / 180 * Math.PI) * radius;
let ay = y + Math.sin(-startAngle / 180 * Math.PI) * yRadius;
let angleMid, bx, by, cx, cy; if (yRadius === 0)
yRadius = radius; target.moveTo(x, y);
target.lineTo(ax, ay); for (let i = 0; i < segs; ++i) {
angle += theta;
angleMid = angle - (theta / 2);
bx = x + Math.cos(angle) * radius;
by = y + Math.sin(angle) * yRadius;
cx = x + Math.cos(angleMid) * (radius / Math.cos(theta / 2));
cy = y + Math.sin(angleMid) * (yRadius / Math.cos(theta / 2));
target.quadraticCurveTo(cx, cy, bx, by);
} target.lineTo(x, y);
}
Drawing Polygons
Draws polygon shapes of specified number of sides.
Usage:
target
— Graphics instance on which dashed line will be drawnx
— X coordinate of the center pointy
— Y coordinate of the center pointsides
— Number of sides (must be greater than 2)radius
— Radius from the center point to points on the polygonangle
— Starting angle offset in degrees
function drawPolygon(target,
x,
y,
sides,
radius,
angle = 0) {
let step = (Math.PI * 2) / sides;
let start = (angle / 180) * Math.PI;
let n, dx, dy; target.moveTo(
x + (Math.cos(start) * radius),
y - (Math.sin(start) * radius)
); for (n = 1; n <= sides; ++n) {
dx = x + Math.cos(start + (step * n)) * radius;
dy = y - Math.sin(start + (step * n)) * radius;
target.lineTo(dx, dy);
}
}
Drawing Stars
Draws a star shaped pattern with specified number of points
Usage:
target
— Graphics instance on which dashed line will be drawnx
— X coordinate of the center pointy
— Y coordinate of the center pointpoints
— Number of points on the starinnerRadius
— Radius of the inside angles of the starouterRadius
— Radius of the outside angles of the starangle
— Starting angle offset in degrees
function drawStar(target,
x,
y,
points,
innerRadius,
outerRadius,
angle = 0) { let step = (Math.PI * 2) / points;
let halfStep = step / 2;
let start = (angle / 180) * Math.PI;
let n, dx, dy; target.moveTo(
x + (Math.cos(start) * outerRadius),
y - (Math.sin(start) * outerRadius)
);
for (n = 1; n <= points; ++n) {
dx = x + Math.cos(start + (step * n) - halfStep) * innerRadius;
dy = y - Math.sin(start + (step * n) - halfStep) * innerRadius;
target.lineTo(dx, dy);
dx = x + Math.cos(start + (step * n)) * outerRadius;
dy = y - Math.sin(start + (step * n)) * outerRadius;
target.lineTo(dx, dy);
}
}
Drawing Gears
Draws a gear shape with the specified number of sides.
Usage:
target
— Graphics instance on which dashed line will be drawnx
— X coordinate of the center pointy
— Y coordinate of the center pointsides
— Number of teeth on the gear (must be greater than 2)innerRadius
— Radius of the indent of the teethouterRadius
— Radius of the teethangle
— Starting angle offset in degreesholeSides
— Polygonal hole number of sides (must be greater than 2)holeRadius
— Radius of the hole
function drawGear(target,
x,
y,
sides,
innerRadius = 80,
outerRadius = 4,
angle = 0,
holeSides = 2,
holeRadius = 0) {
let step = (Math.PI * 2) / sides;
let qtrStep = step / 4;
let start = (angle / 180) * Math.PI;
let n, dx, dy; target.moveTo(
x + (Math.cos(start) * outerRadius),
y - (Math.sin(start) * outerRadius)
);
for (n = 1; n <= sides; ++n) {
dx = x + Math.cos(start + (step * n) - (qtrStep * 3)) * innerRadius;
dy = y - Math.sin(start + (step * n) - (qtrStep * 3)) * innerRadius;
target.lineTo(dx, dy);
dx = x + Math.cos(start + (step * n) - (qtrStep * 2)) * innerRadius;
dy = y - Math.sin(start + (step * n) - (qtrStep * 2)) * innerRadius;
target.lineTo(dx, dy);
dx = x + Math.cos(start + (step * n) - qtrStep) * outerRadius;
dy = y - Math.sin(start + (step * n) - qtrStep) * outerRadius;
target.lineTo(dx, dy);
dx = x + Math.cos(start + (step * n)) * outerRadius;
dy = y - Math.sin(start + (step * n)) * outerRadius;
target.lineTo(dx, dy);
} step = (Math.PI * 2) / holeSides; target.moveTo(
x + (Math.cos(start) * holeRadius),
y - (Math.sin(start) * holeRadius)
); for (n = 1; n <= holeSides; ++n) {
dx = x + Math.cos(start + (step * n)) * holeRadius;
dy = y - Math.sin(start + (step * n)) * holeRadius;
target.lineTo(dx, dy);
}
}
Drawing Bursts
Draw a star burst with the specified number of sides.
Usage:
target
— Graphics instance on which dashed line will be drawnx
— X coordinate of the center pointy
— Y coordinate of the center pointsides
— Number of teeth on the gear (must be greater than 2)innerRadius
— Radius of the indent of the curvesouterRadius
— Radius of the outermost pointsangle
— Starting angle offset in degrees
function drawBurst(target,
x,
y,
sides,
innerRadius,
outerRadius,
angle = 0) {
let step = (Math.PI * 2) / sides;
let halfStep = step / 2;
let qtrStep = step / 4;
let start = (angle / 180) * Math.PI;
let n, dx, dy, cx, cy; target.moveTo(
x + (Math.cos(start) * outerRadius),
y - (Math.sin(start) * outerRadius)
); for (n = 1; n <= sides; ++n) {
cx = x + Math.cos(start + (step * n) - (qtrStep * 3)) * (innerRadius / Math.cos(qtrStep));
cy = y - Math.sin(start + (step * n) - (qtrStep * 3)) * (innerRadius / Math.cos(qtrStep));
dx = x + Math.cos(start + (step * n) - halfStep) * innerRadius;
dy = y - Math.sin(start + (step * n) - halfStep) * innerRadius;
target.quadraticCurveTo(cx, cy, dx, dy);
cx = x + Math.cos(start + (step * n) - qtrStep) * (innerRadius / Math.cos(qtrStep));
cy = y - Math.sin(start + (step * n) - qtrStep) * (innerRadius / Math.cos(qtrStep));
dx = x + Math.cos(start + (step * n)) * outerRadius;
dy = y - Math.sin(start + (step * n)) * outerRadius;
target.quadraticCurveTo(cx, cy, dx, dy);
}
}