Jump to content
Search Community

how to combine svg path animation timeline with svg element morph animation

sum.cumo GmbH test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hey there,

 

I don't see any chance for me to solve this challenge alone, so here it is:

 

- I want to do animate an element on a path

- the path animation is split in progress steps (codepen: inputs )

- every time the chosen progress value is reached, the animated element has a morphing animation

- when a new progress value is chosen, another morphing animation is played, then the progress proceeds and when the chosen progress value is reached, a morphing animation starts at the element

 

I really hope this is not confusing.

 

My original codebase is vue.js. I have another pen 

See the Pen vqoRQq by kerpui (@kerpui) on CodePen

where I pasted the code snipped I already wrote. This snipped is inside of the vue mounted() function. So it is fired only once and works.

 

I need to call this animation on click too. And that's where my trouble begins. As soon as I nest my timelines in functions, this part here gets out of control:

 

TweenMax.to(tlMove, tlMove.duration(), {
progress: this.progressToGo,
ease: Back.easeOut.config(1.3), x: -5
})

 

How can I turn this into a function without loosing the progress state?

 

I really hope this is enough information and not too confusing. I have been trying to solve this with exportRoot too but failed.

 

Thanks in advance

Kerstin

 

See the Pen BgXoOK by kerpui (@kerpui) on CodePen

Link to comment
Share on other sites

10 hours ago, sum.cumo GmbH said:

I really hope this is not confusing.

 

I'm confused. ?

 

If I understand correctly, you need to put this code inside a method.

 

myMethod() {
  TweenMax.to(tlMove, tlMove.duration(), {
    progress: this.progressToGo,
    ease: Back.easeOut.config(1.3), 
    x: -5
  });
}

 

To access your timelines, like tlMove, you can add it to this.

 

this.tlMove = new TimelineMax({ paused: true })

 

 

Now you can reach it.

 

myMethod() {
  TweenMax.to(this.tlMove, this.tlMove.duration(), {
    progress: this.progressToGo,
    ease: Back.easeOut.config(1.3), 
    x: -5
  });
}

 

 

Where is this value is coming from?

 

this.progressToGo

 

 

  • Like 2
Link to comment
Share on other sites

8 minutes ago, OSUblake said:

Where is this value is coming from?

 


this.progressToGo

 

 

 

You can pass the progress into your method like your other code pen.

 

myMethod(progressToGo) {
  TweenMax.to(this.tlMove, this.tlMove.duration(), {
    progress: Number(progressToGo),
    ease: Back.easeOut.config(1.3), 
    x: -5
  });
}

 

  • Like 2
Link to comment
Share on other sites

Thanks for spending your time on this.

I just realized, that I need to nest the variable updates I am doing inside the animation functions using them.

My main problem ist to keep the animation progress and update from its last state when running the animation function again. I guess I would have to create a main timeline?

 

Here is my modified code:

 

  	updateProgressToGo() {
      this.steps.forEach((step) => {
        if (step.to.name === this.$route.name) {
          console.log('step.progress: ', step.progress)
          this.progressToGo = step.progress
        }
      })
    },

    tlStart() {
      const tl = new TimelineMax({ paused: true })
      tl.to(this.$refs.progressFlag, 1, { autoAlpha: 1 })
      return tl
    },

    tlMove() {
      const duration = this.$refs.path.getTotalLength() / this.speed
      const motionPath = MorphSVGPlugin.pathDataToBezier(this.$refs.path, { align: this.$refs.progressFlag})
      const tl = new TimelineMax({ paused: true })

      tl.to(this.$refs.progressFlag, duration, { bezier: {values: motionPath, type:"cubic", autoRotate:true}})

      return tl
    },

    tlEnd() {
      const tl = new TimelineMax({ paused: true })
      tl
        .to(this.$refs.riding, .2, { morphSVG: this.$refs.anticipateFwd, shapeIndex: 0 }, '+=' + Math.abs(this.tlMove().duration() - 0.5))
        .to(this.$refs.riding, .2, { morphSVG: this.$refs.anticipateBack, shapeIndex: 0 })
        .to(this.$refs.riding, .2, { morphSVG: this.$refs.stoppedStandUp, shapeIndex: 0 })
        .to(this.$refs.riding, .3, { morphSVG: this.$refs.walkBackFootFwd, shapeIndex: 0 })

      return tl
    },

    tlMoveWrap() {
      const tl = TweenMax.to(this.tlMove(), this.tlMove().duration(), {
        progress: this.progressToGo,
        ease: Back.easeOut.config(1.3), x: -5
      })

      return tl
    },

 

 

This is how I call the animations on mounted()

this.updateProgressToGo()
this.tlStart().play()
this.tlMoveWrap()
this.tlEnd().play()

 

and this on watch()

this.updateProgressToGo()
this.tlMoveWrap()
this.tlEnd().play()

 

What happens here is that the animation restarts at progress:0 instead of its last position. What did I miss?

 

This is what I am trying the progress to behave like:

 

Link to comment
Share on other sites

13 minutes ago, sum.cumo GmbH said:

My main problem ist to keep the animation progress and update from its last state when running the animation function again. I guess I would have to create a main timeline?

 

No. The problem is you're creating new timelines.

 

For example, this piece of code is creating the move timeline 2 times. Every time you call this.tlMove(), you're creating a new timeline.

 

const tl = TweenMax.to(this.tlMove(), this.tlMove().duration(), {
  progress: this.progressToGo,
  ease: Back.easeOut.config(1.3), x: -5
})

 

 

 

Can you put your code in a simplified demo? It's hard to give advice without see what's going on, and I don't know if what I post will even work or what you're trying to do. You can use Vue on CodePen.

 

On mount, save your timelines and what not to this.

 

this.startTimeline = this.tlStart()
this.startDuration = this.startTimeline.duration()
this.endTimeline = this.tlEnd()

this.updateProgressToGo()
this.startTimeline.play()
this.endTimeline.play(0)
this.tlMoveWrap()

 

 

Now you can reference startTimeline and startDuration here.

 

tlMoveWrap() {
  const tl = TweenMax.to(this.startTimeline, this.startDuration, {
    progress: this.progressToGo,
    ease: Back.easeOut.config(1.3), x: -5
  })
  
  return tl
}

 

 

And on watch:

 

this.updateProgressToGo()
this.wrapTimeline = this.tlMoveWrap()
this.endTimeline.play(0)

 

 

 

  • Like 2
Link to comment
Share on other sites

10 minutes ago, OSUblake said:

For example, this piece of code is creating the move timeline 2 times. Every time you call this.tlMove(), you're creating a new timeline.

 

So you would need to fix this too.

 

.to(this.$refs.riding, .2, { morphSVG: this.$refs.anticipateFwd, shapeIndex: 0 }, '+=' + Math.abs(this.tlMove().duration() - 0.5))

 

To something like this:

 

.to(this.$refs.riding, .2, { morphSVG: this.$refs.anticipateFwd, shapeIndex: 0 }, '+=' + Math.abs(this.startDuration - 0.5))

 

 

Again, I don't know what this timeline is supposed to be doing, so I don't know if the advice I gave about this.endTimeline.play(0) is accurate.

 

 

  • Like 2
Link to comment
Share on other sites

Thank you so much for helping me out!

I will update my code with your advices and test it.

 

Unfortunately I am not allowed to post the SVGs used for morphing etc. until my project is live. That is why I did not create a complete codepen yet. But if the problems I have still remain I will take my time and create some content I am allowed to publish.

I will let you know if it worked out.

Link to comment
Share on other sites

7 minutes ago, sum.cumo GmbH said:

Unfortunately I am not allowed to post the SVGs used for morphing etc. until my project is live. That is why I did not create a complete codepen yet. But if the problems I have still remain I will take my time and create some content I am allowed to publish.

I will let you know if it worked out.

 

You don't have to post any SVGs from your project. The simpler, the better.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...