SVG morphing animation

Hello Processing Forum,

I’m a beginner and this is my first post.

How i can morphing svg with p5.js or Processing? I have two svg files from illustrator, and i want create animation morphing one svg into another.

It depends on the 2 svg

Let’s say both have a child, but one has 53 vertex/vertices, the other none (eg a circle)

Hm. Also even with 53 vertices, it’s only the circumference not every pixel therein.

You could scan the svg from a PGraphics. Then you have two point clouds

Not familiar but I would say it is possible if you have a concept or code to start with. If you don’t have any, my first suggestion is to explore previous posts in the forum:

https://processing.org/examples/morph.html
https://p5js.org/examples/motion-morph.html

https://forum.processing.org/two/discussion/25749/how-to-automatically-morph-transform-blend-from-one-shape-to-another-shape

https://codepen.io/GreenSock/pen/bEzgLd

https://forum.processing.org/one/topic/shape-tween-for-2-x-svg-files.html

https://forum.processing.org/two/discussion/18350/morph-2-images

Next is not Processing related but probly relevant (?) https://codeburst.io/svg-morphing-the-easy-way-and-the-hard-way-c117a620b65f

Kf

Can you say more about what the two svgs are? Do they have the same number of points, in the same order (eg two poses of one object)?

The hardest thing is if you have two conceptually related objects drawn in different styles – eg a pine tree and a palm tree, or a truck and a car. You usually need a domain mapping for the morph to look good (branch=branch, wheel=wheel). That needs to be designed.

For example, I want to make an animation based on the cover of this book. I imagine that the lines will move from center to edge like waves on water.
e9bb5ab6646dc91ce7db5e369401cdfa

So, I have an svg with a hand and an svg with a circle into which the waves will eventually turn.

Perhaps this can be done easier, but I do not know how. I will be glad to advice.

1 Like

this basic sketch shows some properties of the 2 shapes

As I said:

Let’s say both have a child, but one has 53 vertex/vertices, the other none (eg a circle has none vertex but seems to be a fixed entity)

Hm. Also even with 53 vertices, it’s only the circumference not every pixel therein.

You could scan the svg from a PGraphics. Then you have two point clouds

this basic sketch shows some properties of the 2 shapes

PShape sCircle;
PShape sLike;

void setup() {
  // runs once
  size(1800, 1600);
  //
  // The files must be in the data folder
  // of the current sketch to load successfully
  sLike = loadShape("like.svg");
  sCircle = loadShape("circle.svg");
} // func 

void draw() { 
  // runs on and on in a loop
  background(255);
  fill(0);
  stroke(0);
  textSize(22);

  drawShapes();
} // func 

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

void drawShapes() {

  shape(sLike, 110, 110);
  shape(sCircle, 710, 110);

  int count;

  int count2 = sLike.getChildCount();
  println("Like children count: "
    +count2);

  count = sLike.getChild(0).getVertexCount()   ;//Returns the total number of vertices as an int
  println("Like says: "
    +count);
  translate(110, 110); 
  for (int i = 0; i < sLike.getChild(0).getVertexCount(); i++) {
    PVector v = sLike.getChild(0).getVertex(i);
    fill(255, 0, 0); 
    ellipse(v.x, v.y, 7, 7);
  }//for

  println("----------------");

  // --------------------------------------------------
  // Circle

  count2 = sCircle.getChildCount();
  println("Circle children count: "
    +count2);

  count = sCircle.getChild(0).getVertexCount()   ;//Returns the total number of vertices as an int
  println("Circle says: "
    +count);

  noLoop();
}
// =====================================================================

You could scan the svg from a PGraphics. Then you have two point clouds


// https://discourse.processing.org/t/svg-morphing-animation/10482/6

PShape sCircle;
PShape sLike;

ArrayList<PVector[]> list = new ArrayList(); 
PGraphics pg=new PGraphics();

// boolean fly=false;

float amt=0.0;

void setup() {
  // runs once
  size(1800, 1600);
  //
  // The files must be in the data folder
  // of the current sketch to load successfully
  sLike = loadShape("like.svg");
  sCircle = loadShape("circle.svg");
} // func 

void draw() { 
  // runs on and on in a loop
  background(111);
  fill(0);
  stroke(0);
  textSize(22);

  pg = createGraphics(770, 770);
  pg.noSmooth();

  makeShape1();

  // image(pg, 0, 0);

  PVector[] pv= new PVector[0]; 

  // The 3 and the other 3 = the resolution of the scan 
  for (int x=0; x < pg.width; x+=7) {
    for (int y=0; y < pg.height; y+=7) {
      if (pg.get(x, y) < color(1)) 
        //point(x, y) ;
        pv=(PVector[])append(pv, new PVector(x, y));
    }//for
  }//for
  list.add(pv);

  // showOneCloud(0, 0, 0); 

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

  pg = createGraphics(770, 770);
  pg.noSmooth();


  makeShape2();

  // image(pg, 0, 0); 

  //reset 
  pv= new PVector[0]; 

  // The 3 and the other 3 = the resolution of the scan 
  for (int x=0; x < pg.width; x+=3) {
    for (int y=0; y < pg.height; y+=3) {
      if (pg.get(x, y) < color(1)) 
        //point(x, y) ;
        pv=(PVector[])append(pv, new PVector(x, y));
    }//for
  }//for
  list.add(pv);

  // showOneCloud(1, 0, 0); 

  //  drawShapes();

  flyOneCloud(110, 110);
} // func 

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

void makeShape1 () {
  // for init
  pg.beginDraw();
  pg.background(255);
  pg.fill(0);
  pg.shape(sCircle); 
  pg.endDraw();
}

void makeShape2() {
  // for init
  pg.beginDraw();
  pg.background(255);
  pg.fill(0);
  pg.translate(88, 88);
  pg.shape(sLike); 
  pg.endDraw();
}

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

void showOneCloud(int getWhat, 
  float x, float y) {

  PVector[] pvector_Array = list.get(getWhat);

  pushMatrix();
  translate(x, y);
  for (PVector pv : pvector_Array) {
    noStroke(); 
    fill(0, 255, 0);
    float sizeEllipse=1.8; 
    ellipse(pv.x, pv.y, sizeEllipse, sizeEllipse); // use
  }
  popMatrix();
}//func

void flyOneCloud( 
  float x, float y) {

  PVector[] pvector_Array1 = list.get(0);
  PVector[] pvector_Array2 = list.get(1);

  pushMatrix();
  translate(x, y);
  for (int i=0; i<min(pvector_Array1.length, pvector_Array2.length); i++) {

    PVector pv1=pvector_Array1[i];
    PVector pv2=pvector_Array2[i];
    PVector pv3=new PVector(); 

    pv3.x=lerp(pv1.x, pv2.x, amt); 
    pv3.y=lerp(pv1.y, pv2.y, amt);

    noStroke(); 
    fill(0, 255, 0);
    float sizeEllipse=3.2; 

    ellipse(pv3.x, pv3.y, 
      sizeEllipse, sizeEllipse); // use
  }
  popMatrix();

  amt+=.072;
  if (amt>1.0)
    amt=1.0;
}//func

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

void drawShapes() {

  shape(sLike, 110, 110);
  shape(sCircle, 710, 110);

  int count;

  int count2 = sLike.getChildCount();
  println("Like children count: "
    +count2);

  count = sLike.getChild(0).getVertexCount()   ;//Returns the total number of vertices as an int
  println("Like says: "
    +count);
  translate(110, 110); 
  for (int i = 0; i < sLike.getChild(0).getVertexCount(); i++) {
    PVector v = sLike.getChild(0).getVertex(i);
    fill(255, 0, 0); 
    ellipse(v.x, v.y, 7, 7);
  }//for

  println("----------------");

  // --------------------------------------------------
  // Circle

  count2 = sCircle.getChildCount();
  println("Circle children count: "
    +count2);

  count = sCircle.getChild(0).getVertexCount()   ;//Returns the total number of vertices as an int
  println("Circle says: "
    +count);

  noLoop();
}
// =====================================================================

same idea but now we take only the outline of a circle to start from

would probably look better when we took only the outline of the like sign as well



// https://discourse.processing.org/t/svg-morphing-animation/10482/6

PShape sCircle;
PShape sLike;

ArrayList<PVector[]> list = new ArrayList(); 
PGraphics pg=new PGraphics();

// boolean fly=false;

float amt=0.0;

void setup() {
  // runs once
  size(1800, 1600);
  //
  // The files must be in the data folder
  // of the current sketch to load successfully
  sLike = loadShape("like.svg");
  sCircle = loadShape("circle.svg");
} // func 

void draw() { 
  // runs on and on in a loop
  background(111);
  fill(0);
  stroke(0);
  textSize(22);

  // ---------------------------------------
  // handle circle 

  pg = createGraphics(770, 770);
  pg.noSmooth();

  makeShape1();

  // image(pg, 0, 0);

  PVector[] pv= new PVector[0]; 

  // The 3 and the other 3 = the resolution of the scan 
  for (int x=0; x < pg.width; x+=2) {
    for (int y=0; y < pg.height; y+=2) {
      if (pg.get(x, y) < color(1)) 
        //point(x, y) ;
        pv=(PVector[])append(pv, new PVector(x, y));
    }//for
  }//for
  list.add(pv);

  // showOneCloud(0, 0, 0); 

  // ---------------------------------------
  // handle Like  

  pg = createGraphics(770, 770);
  pg.noSmooth();


  makeShape2();

  // image(pg, 0, 0); 

  //reset 
  pv= new PVector[0]; 

  // The 3 and the other 3 = the resolution of the scan 
  for (int x=0; x < pg.width; x+=3) {
    for (int y=0; y < pg.height; y+=3) {
      if (pg.get(x, y) < color(1)) 
        //point(x, y) ;
        pv=(PVector[])append(pv, new PVector(x, y));
    }//for
  }//for
  list.add(pv);

  // showOneCloud(1, 0, 0); 

  //  drawShapes();

  flyOneCloud(110, 110);
} // func 

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

void makeShape1 () {
  // for init
  pg.beginDraw();
  pg.background(255);
  pg.fill(0);
  //pg.shape(sCircle);
  pg.strokeWeight(13);
  pg.noFill();
  pg.ellipse( pg.width/2, pg.height/2, 
    760, 760 ); 
  pg.endDraw();
}

void makeShape2() {
  // for init
  pg.beginDraw();
  pg.background(255);
  pg.fill(0);
  pg.translate(88, 88);
  pg.shape(sLike); 
  pg.endDraw();
}

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

void showOneCloud(int getWhat, 
  float x, float y) {

  PVector[] pvector_Array = list.get(getWhat);

  pushMatrix();
  translate(x, y);
  for (PVector pv : pvector_Array) {
    noStroke(); 
    fill(0, 255, 0);
    float sizeEllipse=1.8; 
    ellipse(pv.x, pv.y, sizeEllipse, sizeEllipse); // use
  }
  popMatrix();
}//func

void flyOneCloud( 
  float x, float y) {

  PVector[] pvector_Array1 = list.get(0);
  PVector[] pvector_Array2 = list.get(1);

  pushMatrix();
  translate(x, y);
  for (int i=0; i<min(pvector_Array1.length, pvector_Array2.length); i++) {

    PVector pv1=pvector_Array1[i];
    PVector pv2=pvector_Array2[i];
    PVector pv3=new PVector(); 

    pv3.x=lerp(pv1.x, pv2.x, amt); 
    pv3.y=lerp(pv1.y, pv2.y, amt);

    noStroke(); 
    fill(0, 255, 0);
    float sizeEllipse=3.2; 

    ellipse(pv3.x, pv3.y, 
      sizeEllipse, sizeEllipse); // use
  }
  popMatrix();

  amt+=.072;
  if (amt>1.0)
    amt=1.0;
}//func

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

void drawShapes() {

  shape(sLike, 110, 110);
  shape(sCircle, 710, 110);

  int count;

  int count2 = sLike.getChildCount();
  println("Like children count: "
    +count2);

  count = sLike.getChild(0).getVertexCount()   ;//Returns the total number of vertices as an int
  println("Like says: "
    +count);
  translate(110, 110); 
  for (int i = 0; i < sLike.getChild(0).getVertexCount(); i++) {
    PVector v = sLike.getChild(0).getVertex(i);
    fill(255, 0, 0); 
    ellipse(v.x, v.y, 7, 7);
  }//for

  println("----------------");

  // --------------------------------------------------
  // Circle

  count2 = sCircle.getChildCount();
  println("Circle children count: "
    +count2);

  count = sCircle.getChild(0).getVertexCount()   ;//Returns the total number of vertices as an int
  println("Circle says: "
    +count);

  noLoop();
}
// =====================================================================
1 Like