如何根据浏览器滚动 y 位置而不是时间来调整 Greensock.js 补间动画?
How to adjust a Greensock.js tween based on browser scroll y position rather than by the time?
如何根据滚动位置手动调整时间?那会是什么样子?基本上 'scroll' 补间?以便补间响应滚动鼠标的 Y 位置而不是仅根据预设时间触发和执行?
恕我直言,这是您需要做的:
- 您将需要 TimelineMax 来对动画进行排序。地方
TimelineMax
中的动画随心所欲。
- 您需要事先确定
window
可以向上滚动到的最大滚动位置。 (这也可以在浏览器调整大小时重新计算,但我在下面的示例中没有考虑到这一点)。你可以弄清楚
this answer 的帮助。另请阅读对该答案的评论。
- 滚动时,您需要转换当前滚动位置
您的 window 对象的百分比为:
var currentScrollProgress=window.scrollY/maxScroll;
这样您的 currentScrollProgress
应该始终在 0
和 1
之间。
TimelineMax
有一个 progress()
方法,它取值范围
来自 0
和 1
其中 0
是动画的初始状态
1
是最终状态。喂这个 currentScrollProgress
进入它,你就完成了。
- 或者,您可以 tween
timeline
本身,即:TweenMax.to(timeline,scrollTweenDuration,{progress:currentScrollProgress,ease:ease});
.
我的例子中使用的代码如下:
HTML:
<div> </div>
<div> </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....
如何根据滚动位置手动调整时间?那会是什么样子?基本上 'scroll' 补间?以便补间响应滚动鼠标的 Y 位置而不是仅根据预设时间触发和执行?
恕我直言,这是您需要做的:
- 您将需要 TimelineMax 来对动画进行排序。地方
TimelineMax
中的动画随心所欲。 - 您需要事先确定
window
可以向上滚动到的最大滚动位置。 (这也可以在浏览器调整大小时重新计算,但我在下面的示例中没有考虑到这一点)。你可以弄清楚 this answer 的帮助。另请阅读对该答案的评论。 - 滚动时,您需要转换当前滚动位置
您的 window 对象的百分比为:
var currentScrollProgress=window.scrollY/maxScroll;
这样您的currentScrollProgress
应该始终在0
和1
之间。 TimelineMax
有一个progress()
方法,它取值范围 来自0
和1
其中0
是动画的初始状态1
是最终状态。喂这个currentScrollProgress
进入它,你就完成了。- 或者,您可以 tween
timeline
本身,即:TweenMax.to(timeline,scrollTweenDuration,{progress:currentScrollProgress,ease:ease});
.
我的例子中使用的代码如下:
HTML:
<div> </div>
<div> </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....