使用 jquery 编写完美动画的正确方法
Proper way to write a perfect animation using jquery
当前场景:
我有一个 divs
列表,其中包含一组根据 divs
存在的数量自动滚动的元素。这个 divs
的列表放在 parent
div
里面并且固定 height
.
要求:
- 如果
divs
的长度小于 4,则不设置动画即滚动。
- 以相同的速度动画直到最后一个
div
并从底部向后滚动到顶部,反之亦然。
- 在悬停任何 child
div
. 时停止滚动
达成:
- 滚动完成,即如果元素少于 4 个则不滚动。
- 悬停在任何 child
div
. 上时滚动停止
- 动画直到底部元素并从头开始。
目前面临的问题:
- 滚动速度不同。开始慢,加速,结束慢。
- 停止滚动的悬停后,再次启动时,再次缓慢启动。
- 到达终点后,它会在那里停留几秒钟,然后从头开始。
HTML
<div id="events_partial" class="container body-content col-md-12 col-lg-12 set-max-height">
<div class="row sec-container" id="secContainer">
<div style="top: -550.242px; opacity: 1;" id="secDetails">
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
</div>
</div>
</div>
CSS
#events_partial {
min-height: 385px !important;
margin-top: 57px;
overflow: hidden;
}
.set-max-height {
max-height: 385px !important;
padding-top: 30px !important;
}
.sec-container {
overflow: hidden !important;
min-height: 200px;
}
#secDetails {
position: absolute;
margin-top: 0px;
}
JS
var animateTime = 50000; //kept varying time because as number of items increases the speed time decreased
var shouldAnimate = true;
if ($("#secDetails .container").length < 4) {
shouldAnimate = false;
}
if ($("#secDetails .container").length >= 4 && $("#secDetails .container").length < 9)
animateTime = 10000;
function marqueePlay() {
if (shouldAnimate) {
$("#secDetails").animate(
{
top: $("#events_partial").height() - $("#secDetails").height(),
opacity: 1
}, animateTime, function () {
$("#secDetails").css("top", 1);
$("#secDetails").css("opacity", 1);
marqueePlay();
});
}
}
marqueePlay();
$("#secDetails").hover(function () {
$(this).stop(); //Stop the animation when mouse in
},
function () {
marqueePlay(); //Start the animation when mouse out
});
非常感谢任何帮助。
这是我能够理解的。
问题:
- 有一个您想要删除的默认 ease 操作。这
慢开始、中快和慢结束动画是一个
可以应用于动画的不同 easing。在你的情况下,
您显然不想要它并且您希望事物以动画形式呈现
非常线性时尚。
- 据我所知,没有直接的方法可以恢复 jQuery 动画。因此在停止 悬停动画后,当您再次调用
marqueePlay()
时,它将尝试在animateTime
变量定义的时间内为剩余距离设置动画。距离减少了,但时间得到了重新应用。因此,您的动画似乎会在一段时间内变慢,然后恢复正常速度。看起来是这样,但实际上,它的行为完全符合预期。
建议的解决方案:
- 根据我上面的理解,你的线性动画可以很
使用
requestAnimationFrame
API. 很容易实现
- 避免 jQuery 的
animate()
方法允许我们使用简单的 pause & resume 我们的动画布尔标志。
下面是正在运行的片段,或者如果您有兴趣将其作为 jsFiddle 查看。
片段:
// [http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/]
window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(callback){window.setTimeout(callback,1000/60);};})();
var secDetails=$('#secDetails');
var container=secDetails.find('.container');
var eventsPartial=$('#events_partial');
var currTop=0;
var destTop=eventsPartial.height()-secDetails.height()-parseInt(eventsPartial.css('margin-top'));
var isPaused=false;
var isFirstLoop=true;
var speed=1;
if(container.length>=4&&container.length<9){
requestAnimFrame(render);
secDetails.hover(function(){isPaused=true;},function(){isPaused=false;});
currTop=destTop;
}
function render(){
requestAnimFrame(render);
if(!isPaused){
secDetails.css({transform:'translate3d(1px,'+roundDecimal(currTop,2)+'px,0px)'});
currTop+=!isFirstLoop?-speed:speed;
if(currTop>0) isFirstLoop=false;
if(currTop<=destTop) currTop=0;
}
}
function roundDecimal(value,place){ return Math.round(value*Math.pow(10,place))/Math.pow(10,place); }
#events_partial {
min-height: 385px !important;
margin-top: 57px;
overflow: hidden;
}
.set-max-height {
max-height: 385px !important;
padding-top: 30px !important;
}
.sec-container {
overflow: hidden !important;
min-height: 200px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="events_partial" class="container body-content col-md-12 col-lg-12 set-max-height">
<div class="row sec-container" id="secContainer">
<div id="secDetails">
<div class="container">
<h3><strong> Program in Place 1 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 2 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 3 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 4 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 5 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 6 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 7 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 8 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
</div>
</div>
</div>
如果有任何不清楚的地方,请告诉我。
P.S。尽管就个人而言,我不喜欢它到达最底部然后再次显示第一个并再次开始动画时发生的突然跳跃。但是我可以理解这是您的场景中的要求,也许它恰好适合这种方式。这是一种品味。如果我按照自己的方式,我会让它们像溜溜球一样上下移动;)。
更新: 这是您的 yoyo jsFiddle。还忘了提一下,您可以使用代码中的 speed
变量来控制动画的速度。希望这有帮助。
当前场景:
我有一个 divs
列表,其中包含一组根据 divs
存在的数量自动滚动的元素。这个 divs
的列表放在 parent
div
里面并且固定 height
.
要求:
- 如果
divs
的长度小于 4,则不设置动画即滚动。 - 以相同的速度动画直到最后一个
div
并从底部向后滚动到顶部,反之亦然。 - 在悬停任何 child
div
. 时停止滚动
达成:
- 滚动完成,即如果元素少于 4 个则不滚动。
- 悬停在任何 child
div
. 上时滚动停止
- 动画直到底部元素并从头开始。
目前面临的问题:
- 滚动速度不同。开始慢,加速,结束慢。
- 停止滚动的悬停后,再次启动时,再次缓慢启动。
- 到达终点后,它会在那里停留几秒钟,然后从头开始。
HTML
<div id="events_partial" class="container body-content col-md-12 col-lg-12 set-max-height">
<div class="row sec-container" id="secContainer">
<div style="top: -550.242px; opacity: 1;" id="secDetails">
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
<div class="container">
<p><h3><strong> Program in Place 1 on 11/22/2015</strong></h3></p>
<p>
Program Description which is a very long text on document and it can be more than 2 lines
</p>
</div>
</div>
</div>
</div>
CSS
#events_partial {
min-height: 385px !important;
margin-top: 57px;
overflow: hidden;
}
.set-max-height {
max-height: 385px !important;
padding-top: 30px !important;
}
.sec-container {
overflow: hidden !important;
min-height: 200px;
}
#secDetails {
position: absolute;
margin-top: 0px;
}
JS
var animateTime = 50000; //kept varying time because as number of items increases the speed time decreased
var shouldAnimate = true;
if ($("#secDetails .container").length < 4) {
shouldAnimate = false;
}
if ($("#secDetails .container").length >= 4 && $("#secDetails .container").length < 9)
animateTime = 10000;
function marqueePlay() {
if (shouldAnimate) {
$("#secDetails").animate(
{
top: $("#events_partial").height() - $("#secDetails").height(),
opacity: 1
}, animateTime, function () {
$("#secDetails").css("top", 1);
$("#secDetails").css("opacity", 1);
marqueePlay();
});
}
}
marqueePlay();
$("#secDetails").hover(function () {
$(this).stop(); //Stop the animation when mouse in
},
function () {
marqueePlay(); //Start the animation when mouse out
});
非常感谢任何帮助。
这是我能够理解的。
问题:
- 有一个您想要删除的默认 ease 操作。这 慢开始、中快和慢结束动画是一个 可以应用于动画的不同 easing。在你的情况下, 您显然不想要它并且您希望事物以动画形式呈现 非常线性时尚。
- 据我所知,没有直接的方法可以恢复 jQuery 动画。因此在停止 悬停动画后,当您再次调用
marqueePlay()
时,它将尝试在animateTime
变量定义的时间内为剩余距离设置动画。距离减少了,但时间得到了重新应用。因此,您的动画似乎会在一段时间内变慢,然后恢复正常速度。看起来是这样,但实际上,它的行为完全符合预期。
建议的解决方案:
- 根据我上面的理解,你的线性动画可以很
使用
requestAnimationFrame
API. 很容易实现
- 避免 jQuery 的
animate()
方法允许我们使用简单的 pause & resume 我们的动画布尔标志。
下面是正在运行的片段,或者如果您有兴趣将其作为 jsFiddle 查看。
片段:
// [http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/]
window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(callback){window.setTimeout(callback,1000/60);};})();
var secDetails=$('#secDetails');
var container=secDetails.find('.container');
var eventsPartial=$('#events_partial');
var currTop=0;
var destTop=eventsPartial.height()-secDetails.height()-parseInt(eventsPartial.css('margin-top'));
var isPaused=false;
var isFirstLoop=true;
var speed=1;
if(container.length>=4&&container.length<9){
requestAnimFrame(render);
secDetails.hover(function(){isPaused=true;},function(){isPaused=false;});
currTop=destTop;
}
function render(){
requestAnimFrame(render);
if(!isPaused){
secDetails.css({transform:'translate3d(1px,'+roundDecimal(currTop,2)+'px,0px)'});
currTop+=!isFirstLoop?-speed:speed;
if(currTop>0) isFirstLoop=false;
if(currTop<=destTop) currTop=0;
}
}
function roundDecimal(value,place){ return Math.round(value*Math.pow(10,place))/Math.pow(10,place); }
#events_partial {
min-height: 385px !important;
margin-top: 57px;
overflow: hidden;
}
.set-max-height {
max-height: 385px !important;
padding-top: 30px !important;
}
.sec-container {
overflow: hidden !important;
min-height: 200px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="events_partial" class="container body-content col-md-12 col-lg-12 set-max-height">
<div class="row sec-container" id="secContainer">
<div id="secDetails">
<div class="container">
<h3><strong> Program in Place 1 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 2 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 3 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 4 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 5 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 6 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 7 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
<div class="container">
<h3><strong> Program in Place 8 on 11/22/2015</strong></h3><p>Program Description which is a very long text on document and it can be more than 2 lines</p>
</div>
</div>
</div>
</div>
如果有任何不清楚的地方,请告诉我。
P.S。尽管就个人而言,我不喜欢它到达最底部然后再次显示第一个并再次开始动画时发生的突然跳跃。但是我可以理解这是您的场景中的要求,也许它恰好适合这种方式。这是一种品味。如果我按照自己的方式,我会让它们像溜溜球一样上下移动;)。
更新: 这是您的 yoyo jsFiddle。还忘了提一下,您可以使用代码中的 speed
变量来控制动画的速度。希望这有帮助。