Skip to content

Instantly share code, notes, and snippets.

@brysonian
Created November 25, 2010 05:25
Show Gist options
  • Save brysonian/714947 to your computer and use it in GitHub Desktop.
Save brysonian/714947 to your computer and use it in GitHub Desktop.
A little hacky class to allow you to animate along a path from a SVG file.
/*
A simple hacky class that takes a path from an PShape and provides functionality similar to bezierPoint on the path. Makes it easy to create animations along a path.
More at https://gist.github.com/714947
*/
class SVGPathAnimation
{
ArrayList<SVGBezier> beziers;
int length;
SVGPathAnimation(PShape path) {
beziers = new ArrayList();
int index = 0;
PVector[] vecs = new PVector[path.getVertexCodeCount() * 3];
for (int i = 0; i < path.getVertexCodeCount(); i++) {
switch (path.getVertexCode(i)) {
case PShape.VERTEX:
vecs[index] = new PVector(path.getVertexX(index), path.getVertexY(index));
index++;
break;
case PShape.BEZIER_VERTEX:
vecs[index] = new PVector(path.getVertexX(index), path.getVertexY(index));
vecs[index+1] = new PVector(path.getVertexX(index+1), path.getVertexY(index+1));
vecs[index+2] = new PVector(path.getVertexX(index+2), path.getVertexY(index+2));
index += 3;
break;
}
}
// ok, add the beziers
for(int i=0; i<vecs.length-3; i+=3) {
if ((vecs[i] != null) && (vecs[i+1] != null) && (vecs[i+2] != null) && (vecs[i+3] != null)) {
SVGBezier b = new SVGBezier(vecs[i], vecs[i+1], vecs[i+2], vecs[i+3]);
addBezier(b);
}
}
length = beziers.size();
}
void addBezier(SVGBezier b) {
beziers.add(b);
}
PVector pointAt(float t) {
int bIndex = floor(length * t);
float bTime = (length * t) - bIndex;
return beziers.get(bIndex).pointAt(bTime);
}
}
class SVGBezier
{
PVector control1, control2, start, end;
SVGBezier(PVector s, PVector cp1, PVector cp2, PVector e) {
start = new PVector(s.x, s.y);
control1 = new PVector(cp1.x, cp1.y);
control2 = new PVector(cp2.x, cp2.y);
end = new PVector(e.x, e.y);
}
void draw() {
bezier(start.x, start.y,
control1.x, control1.y,
control2.x, control2.y,
end.x, end.y);
}
PVector pointAt(float t) {
float x = bezierPoint(start.x, control1.x, control2.x, end.x, t);
float y = bezierPoint(start.y, control1.y, control2.y, end.y, t);
return new PVector(x, y);
}
}
/*
Example program showing how to use the SVGPathAnimation class.
More at https://gist.github.com/714947
*/
PShape path;
SVGPathAnimation ani;
float step = 0;
int steps = 100;
void setup() {
size(500, 500);
smooth();
path = loadShape("path.svg");
ani = new SVGPathAnimation(path.getChild(0));
}
void draw() {
background(255);
shape(path, 0, 0);
fill(0);
noStroke();
PVector v = ani.pointAt(step / steps);
ellipse(v.x, v.y, 10, 10);
step++;
if (step >= steps) step = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment