Jump to content
Search Community

Timing individual 3 simple svg circles to load at different times

CreativeGeek test
Moderator Tag

Go to solution Solved by Rodrigo,

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

HI there! I am in need of some advice and help! I have worked on this for over 3 weeks and I can't seem to find the solution.


I have been using Tweenmax and Scrollmagic in order to make 3 progress circles that fill in a svg path, each loading on different times. I used a drawing path from ScrollMagic and making a timeline so they can load at different times with TweenMax.  I have been able to get everything done thus far, the only thing that is holding me behind is how to manipulate the timing for each circle. I tried adding "+=1" to the second and third circle but it didn't work.


On my codepen, you will find that all three load, but are not loading at separate times like I want to.I would like the first one to load, then the second circle, and third, each having a time in between. with a nice sequence. 


A perfect example of what I am trying to replicate (this demo does not use scrollmagic,so just focus on the behavior progress circles to the righthttps://codyhouse.co/demo/reading-progress-indicator/how-audiences-reacted-to-the-star-wars.html


I hope I can understand what I am doing wrong because I have tried everything.


Thank you and looking forward to the feedback!


See the Pen BzAKLL by sarahabogabir (@sarahabogabir) on CodePen

Link to comment
Share on other sites

  • Solution

Hi and welcome to the GreenSock forums.

 

The issue is that all your paths have the same id:

<!-- CIRCLE 1 -->
<path id="dot" style="stroke-linecap: round; ...></path>

<!-- CIRCLE 2 -->
<path id="dot" style="stroke-linecap: round; ...></path>

<!-- CIRCLE 3 -->
<path id="dot" style="stroke-linecap: round; ...></path>

Then on your JS you have this:

// this variable has all the elements with an id of "dot"
var $dot = $("path#dot");
var $circle_1 = $("#circle_1");
var $circle_2 = $("#circle_2");
var $circle_3 = $("#circle_3");
  
var circle_tween = new TimelineMax()
		.to($dot, 4, { strokeDashoffset: 0, ease:Linear.easeNone})
		.to('#circle_1', 10, {strokeDashoffset: 0,ease:Linear.easeNone})
		.to('#circle_2', 10, {strokeDashoffset: 0, ease:Linear.easeNone})
		.to('#circle_3', 10, {strokeDashoffset: 0, ease:Linear.easeNone})
		.to("path", 1, {stroke:"#ffffff",ease:Linear.easeNone});

So basically all your paths with the dot ID are animating at the same time.

 

You should give every path a different ID, like you're doing with the circles and then create an individual tween for each one.

  • Like 3
Link to comment
Share on other sites

Hi,

 

You're welcome.

 

Also, is there a better way of doing this?

Honestly I don't know. I've never worked with ScrollMagic. Don't get me wrong, the plugin is great and you can create awesome things with it, I just prefer to create my own solutions for this cases. Because of that I couldn't tell you a better way of doing this with ScrollMagic, but creating a single timeline and let the plugin handle it's progress based on the scroll position, seems like the best approach to me.

 

Perhaps you could look in the plugin's docs and issues to see if there's a better way to do it.

 

Unfortunately we have to use our time in GSAP related issues and as much as we enjoy helping users, we can't support third party plugins that work on top of GSAP. You could try the repository's issues page:

 

https://github.com/janpaepke/ScrollMagic/issues

 

Happy Tweening!!

Link to comment
Share on other sites

To add to Craig's answer, Petr is also a moderator here in the forums, so He can definitely chip in with an advice.

 

Also since  srcollmagic is dependant on the scroll position you can increase the scroll amount for each circle and create a controller for each circle instead of a timeline for all of them.

 

Now since the sample provided is based on the length of the each article, there's not much that can be done if that's what you have in mind.

  • Like 2
Link to comment
Share on other sites

Hello Again,

 

It seems that I ran into another small problem. I can't seem to figure out what it is. It is  still related to the same code as before, but just adding one more concept. I am not sure if I should make another post. 

What I am trying to do is to make the first list appear with circle one, so the other two should be hidden, then as you keep scrolling the second circle is turning and the second list is appearing, and so forth. I'm basically trying to swap out the text as I'm scrolling because both items in the container are pinned. The pinning isn't working on codepen but what is most important to me is to get the text to swap in and out according to the circle it belongs to. 

 

In sum:

 -Circle (1) appears with list 1

-Circle 2 appears with list 2

-Circle 3 appears with list 3.

 

In my code you will notice that I decided to include for instance #dot_1 with #bullet_1  in the timeline so each one is paired. It is not throwing me an error so I'm not sure how to pair them up. I tried making a separate timeline but that doesn't seem to work either.

 

 

Here is my codepen:

 

Thank you everyone, I seem to be learning a lot from these forums. 

Link to comment
Share on other sites

Hi,

 

The error you're getting is specific from ScrollMagic:

 

Uncaught TypeError: (intermediate value).setPin(...).setTween is not a function

 

Basically you can't use setTween() after setPin():

var pinBoxScene = new ScrollMagic.Scene ({
  		triggerElement: "#section_2", // point of execution
  		triggerHook: 'onLeave',
  		reverse: true,
		duration: "100%" //pin the element for a total duration of 4000px
	})
	.setPin("#section_2") //pin red box
	.setTween(circle_tween)
	.addTo(controller);

As I mentioned before I don't know a bit about SM, so perhaps you could look in the repository issue and perhaps start a new issue there:

 

https://github.com/janpaepke/ScrollMagic/issues

 

Also you could look at this sample for drawing SVG. Is not the same as you're after but it could help:

 

http://scrollmagic.io/examples/advanced/svg_drawing.html

  • Like 2
Link to comment
Share on other sites

But wouldn't the problem be just about how the information fades in and out? I'm not looking to solve the pinning problem, I know that it's scrollmagic. My apologies if it came across as the primary issue.  Because all I am trying to do is make sure the three paragraphs fade in and out according to whatever circle they belong to. So we can leave scrollmagic out. I just want to understand why the text is not fading in and out.  I hope I explained myself.

 

Thank you again!

Link to comment
Share on other sites

You have to figure how to trigger the concurrent animations based on a specific point in the document.

 

Basically you need to create two instances, one for the circle and one for the paragraph, obviously the circle one has to be longer, because once the paragraph appears, the user will scroll down and the circle has to continue it's drawing. Something like this:

 

Paragraph-1

|-------------------------|

Circle-1                                                                           End of the paragraph

|---------------------------------------------------------------------|

 

That could be translated into this:

var tl = new TimelineLite();

tl
  .to(circle, 10, {vars})
  .to(paragraph, 2, {vars},0);

// the 0 at the ends tells GSAP to put this instance at the start of the timeline

Take a look at this post in the blog to know how timelines work:

http://greensock.com/sequence-video

 

Also check at this video to know how to use the position parameter:

http://greensock.com/position-parameter

 

Unfortunately I don't have time to create a demo now, so hopefully this will help get you on your way.

  • Like 1
Link to comment
Share on other sites

Hi Rodrigo,

 

I understand a lot more now. I started to make a another version, but while doing so I ran into some questions. I googled some of them but they still did not offer a good enough answer.

 

(1) On codepen I used a TimelineMax and TweenMax within the timeline. With the order that you suggested using TimelineLite, how does that differ?

(2) Before I was using .add( ) and with your suggestion I instead started using .to( ) How do these differ? I read online that they are basically the same but the answer still did not justify. 

 

So this was my code before:

// preparevar $dot_1 = $("path#dot_1");
var $dot_2 = $("path#dot_2");
var $dot_3 = $("path#dot_3");


var $circle_1 = $("#circle_1");
var $circle_2 = $("#circle_2");
var $circle_3 = $("#circle_3");


var $bullet_1 = $("#bullet_1"); 
var $bullet_2 = $("#bullet_2");
var $bullet_3 = $("#bullet_3");


// build tween


var circle_tween = new TimelineMax()
.add(TweenMax.to(
 '#dot_1, #bullet_1', 20, {
  strokeDashoffset: 0,
   ease:Linear.easeNone
}
))
.add(TweenMax.to(
 '#dot_2, #bullet_2', 20, {
  strokeDashoffset: 0,
   ease:Linear.easeNone
}
))
.add(TweenMax.to(
 '#dot_3, #bullet_3', 20, {
  strokeDashoffset: 0,
   ease:Linear.easeNone
}
))
.add(TweenMax.to(
'#circle_1', 20, {
  strokeDashoffset: 0,
   ease:Linear.easeNone
},
"+=2")
)
.add(TweenMax.to(
 '#circle_2', 20, {
  strokeDashoffset: 0,
   ease:Linear.easeNone
},
"+=2")
)
.add(TweenMax.to(
 '#circle_3', 20, {
  strokeDashoffset: 0,
   ease:Linear.easeNone
},
"+=2")
)
.add(TweenMax.to(
 "path", 20, {
    stroke:"#ffffff",
     ease:Linear.easeNone
}))

After editing and looking at some of the videos this is what I came up with ( I haven' tested on codepen yet)

 


// prepare
var $dot_1 = $("path#dot_1");
var $dot_2 = $("path#dot_2");
var $dot_3 = $("path#dot_3");


var $circle_1 = $("#circle_1");
var $circle_2 = $("#circle_2");
var $circle_3 = $("#circle_3");


var $bullet_1 = $("#bullet_1"); 
var $bullet_2 = $("#bullet_2");
var $bullet_3 = $("#bullet_3");


var tl = new TimelineLite();
   
   tl.to (#dot_1, 10, {vars})
.to (#bullet_1, 2,  {vars},0);
//zero tells GSAP to place it at the beginning of the timeline


.to (#dot_1, 10, {vars})
.to (#bullet_2, 2, {vars}0);  


.to (#dot_3, 10, {vars})
.to (#bullet_#3, 2, {vars}0);


.to(circle_1, 10, {vars})
.to(circle_2, 10, {vars})
.to(circle_3, 10, {vars});




-Do I need to add "" for #dot after .to ?

-Also how do I still keep the strokeDashofffset and ease:Linear.easeNone inside the timeline (previous code) ?

 

Thank you so much! You have been extremely helpful!

Link to comment
Share on other sites

Hi,

 

The Lite and Max versions differ basically in the available methods each one has to offer. Using the Max classes is useful when you need to perform more complex operations and you need more functionality such as repeat, yoyo, stagger and some other methods. In the case of timelines is pretty much the same, there are some specific methods in the Max class that the Lite class doesn't have. You need to evaluate that in every project, see what you need and then determinate what class to work with. The great thing about GSAP is that you can start with a TimelineLite and then if you need a Max specific method, you can switch to it with no problem, everything will keep working. Take a good look at the docs:

 

http://greensock.com/docs/#/HTML5/Animation/

 

The add() method allows you to include anything you want in a timeline at that specific point, you can include a function, an array of GSAP instances, a single GSAP instance, a label, etc.

 

http://greensock.com/docs/#/HTML5/Animation/TimelineLite/add/

 

The shorthand methods include a TweenLite instance in the timeline with less code and using the familiar constructor syntax:

 

http://greensock.com/docs/#/HTML5/Animation/TimelineLite/to/

 

Again, this depends on your needs, you need to decide what to include based on your particular project.

 

 

-Do I need to add "" for #dot after .to ?

-Also how do I still keep the strokeDashofffset and ease:Linear.easeNone inside the timeline (previous code) ?

That depends, you already have your elements stored in variables as jQuery objects, just pass the name of the variable. You can also use the GSAP selector feature to get the DOM element:

tl.to("#circle_1", 1, {vars});

Normally when I use {vars} I mean the typical constructor object we all use in GSAP, so yes you need to include the properties you're tweening and the easing functions as well, otherwise if you pass {vars}, you'll get an error.

 

Keep checking the videos, docs and other resources (such as the getting started samples) in order to get a better grasp of GSAP.

 

Happy Tweening!!

  • Like 1
Link to comment
Share on other sites

Hi Rodrigo,

 

Thank you again for the response. So the main difference between using TweenMax and TimelineLite are the classes. And as you explained earlier {var} would be any class, or method that can customize any animation? 

 

So for instance, I fixed mine:

var $dot_1 = $("path#dot_1");
	var $dot_2 = $("path#dot_2");
	var $dot_3 = $("path#dot_3");

	var $circle_1 = $("#circle_1");
	var $circle_2 = $("#circle_2");
	var $circle_3 = $("#circle_3");

	var $bullet_1 = $("#bullet_1"); 
	var $bullet_2 = $("#bullet_2");
	var $bullet_3 = $("#bullet_3");

	var tl = new TimelineLite();
   
   	tl.to('#dot_1, 20', {strokeDashoffset: 0, ease:Linear.easeNone})
		.to('#bullet_1', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'},0);
		//zero tells GSAP to place it at the beginning of the timeline

		.to('#dot_2', 20, {strokeDashoffset: 0,ease:Linear.easeNone})
		.to('#bullet_2', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0);  

		.to('#dot_3', 20, {strokeDashoffset: 0,ease:Linear.easeNone})
		.to('#bullet_3', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0);

		.to('#circle_1', 20, {strokeDashoffset: 0, ease:Linear.easeNone})
		.to('#circle_2', 20, {strokeDashoffset: 0, ease:Linear.easeNone})
		.to('#circle_3', 20, {strokeDashoffset: 0, ease:Linear.easeNone});

It still is not working. I know the code is on the right track. I am not sure if it's a semi-colen? I checked the methods and classes in the docs and they were used. 

On codepen the svg circles stopped working: 

 

Everything prior was solved, but it seems like once adding: bullet_1, bullet_2, bullet_3 the whole thing stops working. 

I did watch videos but I think because my effects are different that it may not apply as much as I thought. 

 

I hope to get some feedback here. I know I'm close, It just feels like I've been working on this for a month. 

Link to comment
Share on other sites

You're right is a semicolon.

 

In javascript a semicolon indicates the end of a specific line of code, so when you write this:

tl.to('#dot_1, 20', {strokeDashoffset: 0, ease:Linear.easeNone})
  .to('#bullet_1', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'},0);// this semicolon ends the line

  .to('#dot_2', 20, {strokeDashoffset: 0,ease:Linear.easeNone})
  .to('#bullet_2', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0);

 The first semicolon ends the code line.

 

A little background. In JS libraries such as jQuery, GSAP and many others offer the user the possibility to concatenate methods, by returning the instance after that method. In your code the dot_1 instance is added, then there's another to() instance for bullet_1. The first instance returns the timeline (tl) so basically you can attach another GSAP valid method for a timeline(look in the docs).

 

But when you put a semicolon at the end of the to() instance, or any other GSAP instance, in JS it means that the particular line of code that started with the first tl.to() is now completed. So when you add a new .to() instance after the semicolon, the browser won't know what you're referring to, because you're saying "I want to execute the to() method" and the browser says:"ok, but a method of what object, you're not giving me an object here!!", and an error shows in the console.

 

Just add a semicolon after you inserted all the instances in your timeline:

tl.to('#dot_1, 20', {strokeDashoffset: 0, ease:Linear.easeNone})
  .to('#bullet_1', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'},0)
		//zero tells GSAP to place it at the beginning of the timeline
  .to('#dot_2', 20, {strokeDashoffset: 0,ease:Linear.easeNone})
  .to('#bullet_2', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0)  
  .to('#dot_3', 20, {strokeDashoffset: 0,ease:Linear.easeNone})
  .to('#bullet_3', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0)
  .to('#circle_1', 20, {strokeDashoffset: 0, ease:Linear.easeNone})
  .to('#circle_2', 20, {strokeDashoffset: 0, ease:Linear.easeNone})
  .to('#circle_3', 20, {strokeDashoffset: 0, ease:Linear.easeNone});

Also the codepen is the same link as before and you keep getting the error and there's a big time gap between circle animations, but they're all happening.

 

Perhaps you should refactor your code and make it as simple as possible.

  • 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...