如何根据浏览器滚动 y 位置而不是时间来调整 Greensock.js 补间动画?

How to adjust a Greensock.js tween based on browser scroll y position rather than by the time?

如何根据滚动位置手动调整时间?那会是什么样子?基本上 'scroll' 补间?以便补间响应滚动鼠标的 Y 位置而不是仅根据预设时间触发和执行?

恕我直言,这是您需要做的:

  1. 您将需要 TimelineMax 来对动画进行排序。地方 TimelineMax 中的动画随心所欲。
  2. 您需要事先确定 window 可以向上滚动到的最大滚动位置。 (这也可以在浏览器调整大小时重新计算,但我在下面的示例中没有考虑到这一点)。你可以弄清楚 this answer 的帮助。另请阅读对该答案的评论。
  3. 滚动时,您需要转换当前滚动位置 您的 window 对象的百分比为:var currentScrollProgress=window.scrollY/maxScroll; 这样您的 currentScrollProgress 应该始终在 01 之间。
  4. TimelineMax 有一个 progress() 方法,它取值范围 来自 01 其中 0 是动画的初始状态 1 是最终状态。喂这个 currentScrollProgress 进入它,你就完成了。
  5. 或者,您可以 tween timeline 本身,即:TweenMax.to(timeline,scrollTweenDuration,{progress:currentScrollProgress,ease:ease});.

我的例子中使用的代码如下:

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 [
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();

这里是resulting jsFiddle。希望对你有帮助。

T

虽然 Tahir 的回答是正确和充分的,但是有很多不必要的代码来展示这个例子。

一个更简洁的片段是:

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