0

How would I go about adjusting the time manually based on the scroll position? What might that look like? To basically 'scroll' the tween? So that the tween reacts to the scrolling mouse's Y position rather than just trigger and execute based on a preset time?

Agent Zebra
  • 4,410
  • 6
  • 33
  • 66

2 Answers2

5

IMHO, here is what you'll need to do:

  1. You will need TimelineMax for sequencing your animations. Place your animations in TimelineMax as you like them to be.
  2. You'll need to figure out the maximum scroll position your window can scroll up to, beforehand. (This can also be re-calculated on browser resize as well but I haven't taken this into account in my example below). You can figure out with the help of this answer. Also read the comments on that answer.
  3. Upon scroll, you'll need to convert the current scroll position of your window object into percentage that is: var currentScrollProgress=window.scrollY/maxScroll; such that your currentScrollProgress should always be between 0 and 1.
  4. TimelineMax has a progress() method which takes values ranging from 0 and 1 where 0 being the initial state of the animations and 1 being the final state. Feed this currentScrollProgress into it and you're done.
  5. OR, you can tween the timeline itself that is: TweenMax.to(timeline,scrollTweenDuration,{progress:currentScrollProgress,ease:ease});.

Code used in my example is as follows:

HTML:

<div>&nbsp;</div>
<div>&nbsp;</div>
...

CSS:

html, body { margin: 0; padding: 0; }
div { width: 100%; height: 60px; margin: 2px 0; }
div:nth-child(odd) { background: #cc0; }
div:nth-child(even) { background: #0cc; }

JavaScript:

/*global TweenMax, TimelineMax,Power2*/
var myDIVs=document.querySelectorAll('div'),numDIVs=myDIVs.length;
var timeline=new TimelineMax({paused:true}),duration=.4,ease=Power2.easeOut,staggerFactor=.1,scrollTweenDuration=.4;
var scrollTimeout=null,scrollTimeoutDelay=20,currentScrollProgress=0;
var maxScroll=Math.max(document.body.scrollHeight,document.body.offsetHeight,document.documentElement.clientHeight,document.documentElement.scrollHeight,document.documentElement.offsetHeight)-window.innerHeight; //see [https://stackoverflow.com/a/17698713/3344111]
function init(){
    initTimeline();
    listenToScrollEvent();
    onScroll();
}
function initTimeline(){
    for(var i=0; i<numDIVs; i+=1){ timeline.fromTo(myDIVs[i],duration,{opacity:0},{opacity:1,ease:ease},i*staggerFactor); }
}
function listenToScrollEvent(){
    (window.addEventListener)?window.addEventListener('scroll',debounceScroll,false):window.attachEvent('onscroll',debounceScroll);
}
function debounceScroll(){
    clearTimeout(scrollTimeout);
    scrollTimeout=setTimeout(onScroll,scrollTimeoutDelay);
}
function onScroll(){
    currentScrollProgress=roundDecimal(window.scrollY/maxScroll,4);
    //timeline.progress(currentScrollProgress); // either directly set the [progress] of the timeline which may produce a rather jumpy result
    TweenMax.to(timeline,scrollTweenDuration,{progress:currentScrollProgress,ease:ease}); // or tween the [timeline] itself to produce a transition from one state to another i.e. it looks smooth
}
function roundDecimal(value,place){ return Math.round(value*Math.pow(10,place))/Math.pow(10,place); }
//
init();

Here is the resulting jsFiddle. Hope it helps.

T

Community
  • 1
  • 1
Tahir Ahmed
  • 5,687
  • 2
  • 17
  • 28
1

While Tahir's answer is correct and sufficient, there's a lot of unnecessary code to show the example.

A more concise snippet is:

var max_scroll = document.body.offsetHeight - window.innerHeight;

win.addEventListener('scroll', function(){
    var scroll_perc = parseFloat(Math.min(window.pageYOffset / max_scroll, 1).toFixed(2));

    TweenMax.to(tl, 0, {
        progress: scroll_perc
    });
});

var tl = new TimelineMax({paused: true});
// the rest of your timeline....
evu
  • 1,031
  • 2
  • 10
  • 29