Follow vector path

Hi Everyone,

I am searching for a solution to move objects along vector paths (ex.: svg). I thought is a simple thing as the AE Lottie plugin is using something similar (AE animations converted to SVG - JSON to reproduce animation in Javascript)

lottie.loadAnimation({
container: element, // the dom element that will contain the animation
renderer: ‘svg’,
loop: true,
autoplay: true,
path: ‘data.json’ // the path to the animation json
});

Maybe someone has a simple solution?

can you show a simple example sketch that shows the data? Preferable not svg but an ArrayList of Vectors e.g.?

Thanks for the reply Chrisir.

A very simple path .json data in Lottie looks like this:

{“v”:“4.5.5”,“fr”:60,“ip”:0,“op”:65,“w”:500,“h”:500,“ddd”:0,“assets”:[],“layers”:[{“ddd”:0,“ind”:0,“ty”:4,“nm”:“doneIcon contornos”,“ks”:{“o”:{“a”:0,“k”:100},“r”:{“a”:0,“k”:0},“p”:{“a”:0,“k”:[250,250,0]},“a”:{“a”:0,“k”:[250,250,0]},“s”:{“a”:0,“k”:[100,100,100]}},“ao”:0,“shapes”:[{“ty”:“gr”,“it”:[{“ind”:0,“ty”:“sh”,“ks”:{“a”:0,“k”:{“i”:[[0,0],[0,0],[0,0]],“o”:[[0,0],[0,0],[0,0]],“v”:[[-167.614,16.761],[-68.75,116.193],[167.614,-116.193]],“c”:false}},“nm”:“Trazado 1”,“mn”:“ADBE Vector Shape - Group”},{“ty”:“tm”,“s”:{“a”:1,“k”:[{“i”:{“x”:[0.667],“y”:[1]},“o”:{“x”:[0.333],“y”:[0]},“n”:[“0p667_1_0p333_0”],“t”:0,“s”:[0],“e”:[100]},{“t”:24}],“ix”:1},“e”:{“a”:0,“k”:0,“ix”:2},“o”:{“a”:0,“k”:0,“ix”:3},“m”:1,“ix”:2,“nm”:“Recortar trazados 1”,“mn”:“ADBE Vector Filter - Trim”},{“ty”:“st”,“c”:{“a”:0,“k”:[0.3,0.91,0.02,1]},“o”:{“a”:0,“k”:100},“w”:{“a”:0,“k”:42},“lc”:1,“lj”:1,“ml”:10,“nm”:“Trazo 1”,“mn”:“ADBE Vector Graphic - Stroke”},{“ty”:“tr”,“p”:{“a”:0,“k”:[253.614,247.648],“ix”:2},“a”:{“a”:0,“k”:[0,0],“ix”:1},“s”:{“a”:0,“k”:[100,100],“ix”:3},“r”:{“a”:0,“k”:0,“ix”:6},“o”:{“a”:0,“k”:100,“ix”:7},“sk”:{“a”:0,“k”:0,“ix”:4},“sa”:{“a”:0,“k”:0,“ix”:5},“nm”:“Transformar”}],“nm”:“Grupo 1”,“np”:3,“mn”:“ADBE Vector Group”}],“ip”:0,“op”:66,“st”:0,“bm”:0,“sr”:1}]}

I am testing a few things here: https://codepen.io/czelmatyas/pen/PLJGVG (sorry for the super messy code). I would like to achieve more complex movements of the ellipse I am animating, preferably following a vector path.

Thanks

here is a simple movement using curvepoint (comparable to lerp)

A more complex sketch

here is a more complex sketch:

The ArrayList<PointMy> listPointMy are the vectors (I my sketch this is a track for a rollercoaster);
you want to look at function rollerCoaster()

Chrisir


// Track for the rollercoaster: 
// holding the curveVertex points in 3D - the core data. Here you add and edit your points. 
ArrayList<PointMy> listPointMy = new ArrayList();

// move a sphere along the curve (Rollercoaster) 
boolean showRollercoasterFlag = false; 
int showRollercoaster_i; // current number of sphere on track for the Rollercoaster CAR 
int i2=0; // counter for the taken steps between 2 single points of track for rollercoaster  
boolean firstTime=true;
PVector camPV=new PVector();

// ---------------------------------------------------------------------
// CORE functions 

void setup() {
  size(1440, 880, P3D);
  background(255);

  makeArrayList();  // the track
}// func 

void draw() {
  drawForNormal();
}//draw

//------------------------------------------------------------------------------

void drawForNormal() {

  background(255);
  lights();

  // show ArrayList
  showArrayList(); 

  if (true) {
    rollerCoaster();
  }//if
}// func 

// -------------------------------------------------------------------------

void makeArrayList() {
  // http://de.wikipedia.org/wiki/Ellipse#Ellipsengleichung_.28Parameterform.29

  float radiusX=300; 
  float radiusY=110;

  float centerX=0;
  float centerZ=0; 

  for (int angleStar = 0; angleStar <= 360; angleStar += 4) {

    float starX = centerX + (cos (radians(angleStar)) * radiusX);
    float starY = 0;
    float starZ = centerZ + (sin (radians(angleStar)) * radiusY);

    // the part on the right gets elevated 
    if (starX>220) {
      starY=map(starX-220, 0, 310, -10, -420);
    }

    PVector newPVector = new PVector(starX, starY, starZ);
    listPointMy.add (  new PointMy ( newPVector, false) );   // 3D
  }//for
  listPointMy.get(65).p.y -= 155;
}//func 

void showArrayList() {
  // show the curve 

  noFill();
  stroke(0);
  beginShape();
  int i=0;
  if (listPointMy.size()>0) {
    listPointMy.get(i).useAsCurveVertexPVector();
    for ( i = 0; i < listPointMy.size(); i++) {
      listPointMy.get(i).useAsCurveVertexPVector();
    }
    i=listPointMy.size()-1;
    listPointMy.get(i).useAsCurveVertexPVector();
  }//if
  endShape();

  //show the points (additionally)
  noStroke();
  float rad=3;
  for ( i = 0; i < listPointMy.size(); i++) {
    PointMy pm = listPointMy.get(i);
    PVector pv=pm.p;
    // if we are close to the mouse, color green, else red
    if (dist(mouseX, mouseY, pv.x, pv.y)<11 || pm.selected) {
      // near to mouse 
      fill( 0, 255, 0); // green
      rad=7;
    } else {
      // normal 
      fill(255, 0, 0);  // red
      rad=3;
    }
    pm.showAsSphere(rad);
  }//for
}//func

// ------------------------------------------------------------------------

// interprete the spline as a rollercoaster track with a CAR on it

void rollerCoaster() {

  ellipseMode(CENTER);

  // get two points between which the CAR currently is running  
  PointMy pm1=listPointMy.get( showRollercoaster_i );
  PointMy pm2=listPointMy.get( showRollercoaster_i+1 ); 

  // get dist between 2 points 
  float dist1 = pm1.p.dist(pm2.p);
  // calculate the steps between the 2 points depending on dist1 between them (smooth running) 
  int steps; // = 9;
  steps = int(dist1 / 2);

  // calc t (can be seen as amt in lerp() / curvePoint) 
  float t = i2 / float(steps);

  // similar to lerp() wth amt:  
  float x = curvePoint(pm1.p.x, pm1.p.x, pm2.p.x, pm2.p.x, t);
  float y = curvePoint(pm1.p.y, pm1.p.y, pm2.p.y, pm2.p.y, t);
  float z = curvePoint(pm1.p.z, pm1.p.z, pm2.p.z, pm2.p.z, t);

  // different camera view for rollercoaster view
  setRollerCoasterCamera(x, y, z, t); 

  // show ball&box [the rollercoaster car] 
  if (true) { 
    fill(255, 2, 244);
    noStroke(); 
    pushMatrix(); 
    translate(x, y, z);
    box(9);
    translate(0, -5, 0);
    sphere(7); 
    popMatrix();
  }

  i2++; 
  if (i2>steps) {
    showRollercoaster_i++; 
    if (showRollercoaster_i>listPointMy.size()-2) { // little rough management at the end of arraylist... ??? 
      showRollercoaster_i=0;
    }//if
    i2=0;
  }//if
}//func

void setRollerCoasterCamera(float x, float y, float z, 
  float t) {
  // camera view for rollercoaster view 
  camPV = getCameraPositionFromBall(x, y, z); 
  camera(camPV.x, camPV.y-4, camPV.z, 
    0, 0, 0, 
    0, 1, 0);
}//func 

PVector getCameraPositionFromBall(float bx, float by, float bz) {

  // leading to a result that has the points nicely on a circle. 

  // Usage: centerPV is at the center of a virtual circle, outsidePV on its circumference. 
  // Function returns the point (new PVector(x1, y1, z1)) with the radius radius1 that prolongs the Radius 
  // from centerPV over outsidePV (further out) to the resulting PVector new PVector(x1, y1, z1).

  PVector centerPV  = new PVector(0, 0, 0); 
  PVector outsidePV = new PVector(bx, by, bz);

  float angle1 = atan2(outsidePV.z-centerPV.z, outsidePV.x-centerPV.x);

  float radius1 = 0;// pre-init
  // adjust : we calculate the radius here
  // radius1 = 700/2 + 120;

  float d0 = centerPV.dist(outsidePV);
  // d0 = dist(centerPV.x, centerPV.y, outsidePV.x, outsidePV.y);
  float d1 = map (d0, 10, 1000, 140, 1450); // float d1 = map (d0, 10, 1000, 40, 1350);
  radius1 = d1; 

  float x1 = cos(angle1) * radius1 + centerPV.x;
  float y1 = 0;
  //y1 = lerp(centerPV.y, outsidePV.y, map (d0, 10, 1000, 1.5, 1.9));
  //y1 = lerp(centerPV.y, outsidePV.y, 1.3);
  y1 = outsidePV.y-26;
  float z1 = sin(angle1) * radius1 + centerPV.y;

  return new PVector(x1, y1, z1);
} // method 

// ==================================================================

class PointMy {

  // one point one the track 

  PVector p;  // position 
  boolean selected=false; // selected y/n

  float theX, theY;  // screenX and screenY

  // constructor 
  PointMy( PVector p_, boolean selected_ ) {
    p        = p_.copy();
    selected = selected_;
  } // constructor

  void showAsSphere( float rad ) {
    pushMatrix();
    translate(p.x, p.y, p.z);

    theX = screenX(0, 0, 0);  // monitor and store screen position 
    theY = screenY(0, 0, 0);

    noStroke();
    sphere(rad); 
    popMatrix();
  } // method

  void useAsCurveVertexPVector() {
    // like curveVertex but gets a PVector as input  
    // (just an easy way to use vectors for curveVertex)
    curveVertex(p.x, p.y, p.z);
  } // method 
  //
}//class
//

2 posts were split to a new topic: Can p5.js export lottie files?