Advanced Drawing with Pixi.js

Jason Sturges
Level Up Coding
Published in
7 min readAug 9, 2020

--

Photo by Joel Filipe on Unsplash

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 drawn
  • x1 — Starting position along x-axis
  • y1 — Starting position along y-axis
  • x2 — Final position along x-axis
  • y2 — Final position along y-axis
  • dashLength — Length of each dash, in pixels
  • spaceLength — 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 drawn
  • x — X coordinate of the starting point
  • y — Y coordinate of the starting point
  • radius — Radius of the arc
  • arc — Sweep of the arc (negative values draw clockwise)
  • startAngle — Starting offset angle in degrees
  • yRadius — 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 drawn
  • x — X coordinate of the center point
  • y — Y coordinate of the center point
  • radius — Radius of the wedge
  • arc — Sweep of the arc (negative values draw clockwise)
  • startAngle — Starting angle in degrees
  • yRadius — 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 drawn
  • x — X coordinate of the center point
  • y — Y coordinate of the center point
  • sides — Number of sides (must be greater than 2)
  • radius — Radius from the center point to points on the polygon
  • angle — 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 drawn
  • x — X coordinate of the center point
  • y — Y coordinate of the center point
  • points — Number of points on the star
  • innerRadius — Radius of the inside angles of the star
  • outerRadius — Radius of the outside angles of the star
  • angle — 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 drawn
  • x — X coordinate of the center point
  • y — Y coordinate of the center point
  • sides — Number of teeth on the gear (must be greater than 2)
  • innerRadius — Radius of the indent of the teeth
  • outerRadius — Radius of the teeth
  • angle — Starting angle offset in degrees
  • holeSides — 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 drawn
  • x — X coordinate of the center point
  • y — Y coordinate of the center point
  • sides — Number of teeth on the gear (must be greater than 2)
  • innerRadius — Radius of the indent of the curves
  • outerRadius — Radius of the outermost points
  • angle — 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);
}
}

--

--

Avant-garde experimental artist — creative professional leveraging technology for immersive experiences