Jump to content
Search Community

Unable to find a solid architecture for panel-based onepager.

katerlouis 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

Hello guys,

I need some ideas on a good architecture for a panel-based onepager.

 

I have 13 full width & height panels. 

Each panel has an "initialization" timeline (which also handles outro animations of the previous one, if needed)

Each panel can have multiple "agile" timelines (repeat: -1) to make the panels come alive (flying birds, blinking eyes, slightly morphing river or smoke, with lots of randomness)

 

An initialization animation must only happen once per panel. Meaning: When you traverse back to the top and then go down again, there should not be initialization animations. Only hard cuts. Reason: user traverses faster.

 

When one panel is visible the agile animations of all others should pause (not reset). 

The agile animations should should always play on, no matter if this is "the second view of this panel".

 

 

For switching panels I have a function called `activatePanel()` which gets the index of the desired `section.panel`. 

activatePanel() then looks if an function `anim[ <ID OF section.panel:eq> ]` exists and then executes it.

 

 

The faced challanges I can't find a convenient solution for are:

1. storing the timelines in a clever way so there are available to use .pause(), .seek() etc. "from the outside"

2. (kinda resulting out of issue 1.) pausing all the agile animation timelines of the inactive panels

 

 

I know you have a deal with Chris Coyier; but this problem is just based on the whole project. 

So I kindly ask you to visit http://beta.richmodis.de/  (navigate with swiping to get animations or with arrow keys up and down to skip animations)

 

I understand if you can't / won't / don't want to look over the whole project.

In that case I'd appreciate some tips on architecture for a project structured like mine.

 

 

 

Thanks for your help and understanding in advance,

I am overworked :o

 

 

René

 

 

[EDIT]:

I also need to keep track that `activatePanel()` gets blocked until a running init animation is finished. I got most of these things done somehow, but it feels very klonky, is definitely not well-aranged etc.–

Link to comment
Share on other sites

I know you have a deal with Chris Coyier; but this problem is just based on the whole project. 

 

On what basis do you make such statement?

 

------

 

As for your questions. I'll have a question of my own: Where is "outside"?

 

One way to be clever about storing references is to have them structured following some logic and/or index. That way, you can use a check to see where you are in said index and loop thru the contents of the section.

 

As you loop, check if such children timelines exist and pause/unpause them.

 

You can have each section contain a timeline named "section" + the section number, the number would be your index, as an example.

 

Another way is to have an object and store the references there, then, again, you loop over it and check is such timeline exists in the object.

  • Like 2
Link to comment
Share on other sites

The Chris comment was 100% irony– That's me lightening the mood after I don't provide a CodePen example (repeatedly).

 

Uff, didn't think about the "outside" term :D

 

By "outside" I mean, that whenever needed another function can access the timeline object.

 

Another problem I'm facing is resetting.

I have a timeline which sets a class via .set(".el", { className: "+= someclass" });

When I reset this timeline via .pause().seek(0) the class `someclass` is still assigned to the element.

I am really really confused right now.. 

 

 

What I've done now to tackle my other issues:

I made the class `Panel`, which gets a anonymous function containing the initializtation timeline and returns the timeline object. 

Panel = function( param ) {

	var initFunction = param;
	var initTl;

	var initPlayed = false;

	this.init = function() {

		if (initPlayed) { d("init anim already played"); return; }

		initTl = initFunction();

		initPlayed = true;
	}

	this.reset = function() {
		initTl.pause(0, true).seek(0);
	}

}

But at first I planned to do it as followed, in order to have the timeline already calculated

Panel = function ( param ) {
    var initTl = param().pause();

...
}

// and then do
anim = {};

anim["panel-product"] = new Panel(function() {
    var tl = new TimelineMax();
    tl.to....

    return tl;
});

But then I realized that all the .set()s and .from()s etc. get already applied (of course they do..) when Panel() calls the timelinefunction and pauses the timeline, which I can't have, since people may use the arrow keys for hard-cut-transitions. 

 

 

I am muddling up so many things in my head right now O.O

Link to comment
Share on other sites

Irony is very hard to be noticed in written format...

 

Had a quick glance at your site. I'm afraid I'm not going to comb over 11,000 lines of JS code...

 

What I would probably do, if I were in your situation would be:

 

Have one major init function that creates all animations and store them in a object with a particular structure. Then, as said, I'd keep track of an index to know where in the page the user is and match the relevant timeline as needed. With only one init function and saving your timelines into an Object, you won't lose anything and you won't be having to check if you had already initialised or not the particular timeline.

function genericTimelineBuilder(args) {
 var tl1 = callToTimelineConstructor();
 var tl2 = callToAnotherTimelineConstructir();
 var tl3 = asAbove();

  // Return the timelines as object values
  return {
   tl1: tl1,
   tl2: tl2,
   tl3: tl3,
   // You can also have methods here for ease of use
   pauseAll: function() {
    tl1.pause();
    tl2.pause();
    tl3.pause();
  },
 }
}

var majorObj = genericTimelineBuilder(yourArgs);

And so on...

 

You can attache callbacks into your timelines that would enable/disable the navigation to the next stage if you required. You can also create methods into the object to check if any of the timelines are playing and return true or false. All sorts of behaviour and logic can be implemented.

 

And you can separate your timelines into other functions to keep the main one better organised.

 

If I had some spare time I'd put a codePen with a more complete example but I'm afraid you'll have to hang on there for now.

 

Do bear in mind this in not the only nor the best way of achieving it. But it is a way.

  • Like 3
Link to comment
Share on other sites

  • 3 weeks later...

Thank you very much for this detailed explanation!

 

I think it I'm too late for this project, though :D

 

Still, this is a very interesting topic and seems to be a huge weakness of mine.

 

 

Are there famous topics regarding this subject in the forums already? Or do you know any other "best practices in javascript animation architecture with GSAP"? 

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