我想要顺利过渡 css 属性,然后我想立即更改 css 属性值,然后我想再次附加过渡。为了更好地理解,请参阅以下示例:
if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
$(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
setInterval(function() {
$('.marquee-wrapper').css("transition", "none");
$('.marquee-wrapper').css("transform", "translateY(100px)"); //This should Immediately change translateY to 100px without smooth transition. But this doesn't happen without adding a delay before the below written line
// Its weird why javascript engine executes the below line before executing this line
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
}, 3000);
.marquee {
margin: auto;
width: 600px;
height: 200px;
overflow: auto;
}
.marquee-wrapper {
transform: translateY(0);
}
.marquee-content {
margin: 0;
padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
<div class="marquee-wrapper">
<div class="marquee-content">
Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
= $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
Similarly you can use pause the marquee any time using $mq.marquee('pause');.
</div>
</div>
</section>
正如您在setInterval中看到的,我首先将过渡设置为none,然后将Y转换为100px。现在原则上,这应该突然将div 转换为 100px,但在将div 移动到 100px JavaScript 引擎执行下一行并重新分配过渡之前,这不会发生。在下面的示例中,我在重新分配转换之前给出了 100 毫秒的延迟,它可以工作:
if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
$(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
setInterval(function() {
$('.marquee-wrapper').css("transition", "none");
$('.marquee-wrapper').css("transform", "translateY(100px)"); //This Immedeately change translateY to 100px without smooth transition now
setTimeout(function(){
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
},100);
}, 3000);
.marquee {
margin: auto;
width: 600px;
height: 200px;
overflow: auto;
}
.marquee-wrapper {
transform: translateY(0);
}
.marquee-content {
margin: 0;
padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
<div class="marquee-wrapper">
<div class="marquee-content">
Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
= $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
Similarly you can use pause the marquee any time using $mq.marquee('pause');.
</div>
</div>
</section>
我的问题是:
- 在更改翻译属性之前,如何停止 javscript 引擎以重新分配转换属性,而不会有任何延迟?
- 为什么 javscript 引擎在当前行(
$('.marquee-wrapper').css("transform", "translateY(100px)");
之前在脚本中执行即将到来的行($('.marquee-wrapper').css("transition", "transform 3s linear");
)
将transition
和transform
CSS 属性分组到单个语句中会给出正确的结果,而不必使用 100 毫秒的延迟:
$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
setInterval(function () {
$('.marquee-wrapper').css({ transition: "none", transform: "translateY(100px)" });
$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
}, 3000);
if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
$(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
setInterval(function () {
$('.marquee-wrapper').css({ transition: "none", transform: "translateY(100px)" });
$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
}, 3000);
.marquee {
margin: auto;
width: 600px;
height: 200px;
overflow: auto;
}
.marquee-wrapper {
transform: translateY(0);
}
.marquee-content {
margin: 0;
padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
<div class="marquee-wrapper">
<div class="marquee-content">
Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
= $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
Similarly you can use pause the marquee any time using $mq.marquee('pause');.
</div>
</div>
</section>
该行为的原因可能是同时设置两个 CSS 属性会立即触发页面的重新绘制,而单独设置它们不会。
已知某些 Javascript 命令会导致重绘。获取元素的offsetHeight
是最常提到的(见这篇文章)。事实上,本文使用它来解决与此处介绍的非常相似的 CSS 过渡问题。如果我们通过获取过渡之间的元素高度来测试该方法,我们会看到结果的行为确实是正确的:
$('.marquee-wrapper').css("transition", "none");
$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').height(); // Force a repaint
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
$(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
setInterval(function () {
$('.marquee-wrapper').css("transition", "none");
$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').height(); // Force a repaint
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
}, 3000);
.marquee {
margin: auto;
width: 600px;
height: 200px;
overflow: auto;
}
.marquee-wrapper {
transform: translateY(0);
}
.marquee-content {
margin: 0;
padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
<div class="marquee-wrapper">
<div class="marquee-content">
Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
= $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
Similarly you can use pause the marquee any time using $mq.marquee('pause');.
</div>
</div>
</section>
我将向您解释为什么会发生这种情况。
我一直在处理javascript动画,并且有许多js库(专注于数学)考虑了操作延迟(I/O可用性策略)和超时。
在第一个代码片段中,您有以下操作:
$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').css("transition", "transform 3s linear");
变换
Css 变换方法使用基于矩阵的操作,计算成本高。有些css动画框架确实使用图形处理器单元(具有矩阵运算符),其工作速度提高了几倍,以实现流畅,实时的图形操作。
过渡
Css Transition 是另一种图形操作,但不是通过纯[matrix op matrix]
转换来修改 css 实体,它使用右一维运算符,这意味着您的 css 矩阵是用[matrix op array]
修改的。
然后,您选择的线性模式会在元素的位置上应用线性插值(可能只有几个积分运算符)。它具有低计算成本,这使得整个转换操作的计算速度更快。
这是在某种时间轴中发生的执行的架构:
transform calculation-process
exec -----------------------------------------> applied
| | | |
| | | |
| | | |
transition | calculation-process | |
--------- exec ---------------------> applied ---------
由于 javascript 顶部的 jQuery 具有非阻塞代码执行(对于依赖于 i/o 的函数,除非您对其进行同步编码),这是 javascript 异步策略的基础,因此允许下一个操作甚至在先例结束之前执行。
使用超时函数进行修复可确保在运行以下代码之前完成转换操作,但作为限制,它仅适用于计算速度与当前客户端处理器相似的客户端。(如果您在PC中开发它,那么它可能会在智能手机中失败)
我在代码中使用的另一个解决方案是使用 jquery 回调。看看 jquery animate() 文档,其中显示了:
.animate( 属性 [, 持续时间 ] [, 缓动 ] [, 完成 ] )
在您的示例中,它将如下所示:
$('.marquee-wrapper').animate({"transform": "translateY(100px)"}, function(){
// this code runs after transform ends...
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
});
我发现许多有用的库可以"认真"地玩动画。这些是我使用的一些库:
D3.js
弹跳.js
安全.js
纸张.js
我希望它有所帮助。
更新
这里有一个关于动画和 css 过渡的很好的 SO 答案。
我认为这里有一些很好的答案告诉你为什么它确实有效,但如果你想要一个更支持浏览器的动画,请使用 jQueryanimations
.
$wrap = $(".marquee-wrapper")
$con = $(".marquee-content");
cHeight = $con.outerHeight(true)
if ($(".marquee").height() < cHeight) {
$con.clone().appendTo( $wrap );
}
function animate() {
$wrap.animate({
top: "-=" + cHeight
}, 3000, "linear", function() {
$(this).css("top", "0");
animate();
});
}
animate();
//Cache values
$wrap = $(".marquee-wrapper")
$con = $(".marquee-content");
cHeight = $con.outerHeight(true)
if ($(".marquee").height() < cHeight) {
$con.clone().appendTo( $wrap );
}
function animate() {
$wrap.animate({
top: "-=" + cHeight //minus height from the value of top
},
3000, // milisecs of animations length
"linear", // type of animations
function() { //function to run after animation is complete
$(this).css("top", "0");
animate();
});
}
animate(); //Run function in the beginning
.marquee {
margin: auto;
width: 600px;
height: 200px;
overflow: auto;
position: relative;
}
.marquee-wrapper { position: absolute; }
.marquee-content {
margin: 0;
padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
<div class="marquee-wrapper">
<div class="marquee-content">
Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
= $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
Similarly you can use pause the marquee any time using $mq.marquee('pause');.
</div>
</div>
</section>
JSfiddle