简体   繁体   English

如何立即删除css过渡?

[英]How to remove css transitions without delay?

I want a transition a css property smoothly then I want immediate change in css property value and then I want to attach the transition back again. 我希望顺利转换css属性然后我想立即更改css属性值然后我想再次附加转换。 To better understand see the following example: 为了更好地理解,请参阅以下示例:

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

As you can see in the setInterval I first set transition to none then translateY to 100px. 正如您在setInterval中看到的,我首先将转换设置为none,然后将translateY转换为100px。 Now in principle this should suddenly translate the div to 100px but this doesn't happen before moving div to 100px javascript engine executes the next line and reassign transition. 现在原则上这应该突然将div转换为100px,但这不会发生在将div移动到100px之前javascript引擎执行下一行并重新分配转换。 In the below example I have given a 100ms delay before reassigning the transition and it works: 在下面的例子中,我在重新分配转换之前给出了100ms的延迟,它可以工作:

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

My questions are: 我的问题是:

  1. How do I stop javscript engine to reassign transition property before making changing translate property, without any delay? 如何在更改translate属性之前阻止javscript引擎重新分配transition属性,没有任何延迟?
  2. Why does javscript engine excutes a forthcoming line( $('.marquee-wrapper').css("transition", "transform 3s linear"); ) in script before the current line( $('.marquee-wrapper').css("transform", "translateY(100px)"); ) 为什么javscript引擎会在当前行( $('.marquee-wrapper').css("transform", "translateY(100px)");之前的脚本中执行即将到来的行( $('.marquee-wrapper').css("transition", "transform 3s linear"); $('.marquee-wrapper').css("transform", "translateY(100px)");

Grouping the transition and transform CSS properties in a single statement gives the correct result, without having to use the 100 ms delay: 在单个语句中对transitiontransform 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 eg 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> 


The reason for that behavior could be that setting both CSS properties at once triggers an immediate repaint of the page whereas setting them separately doesn't. 这种行为的原因可能是,设置两个CSS属性会立即触发立即重新绘制页面,而单独设置它们则不会。

Some Javascript commands are known to cause a repaint. 已知一些Javascript命令会导致重绘。 Getting the offsetHeight of an element is the one mentioned most often (see this post ). 获取元素的offsetHeight是最经常提到的(见本文 )。 As a matter of fact, it was used in this article to solve a problem with CSS transitions quite similar to the one presented here. 事实上,在本文中使用它来解决CSS转换的问题与此处介绍的问题非常类似。 And if we test that method by getting the element height between the transitions, we see that the resulting behavior is indeed correct: 如果我们通过获取转换之间的元素高度来测试该方法,我们会看到结果行为确实是正确的:

$('.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 eg 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> 

I shall explain you why this happens. 我会解释你为什么会这样。
I've been dealing with javascript animations, and there are many js libraries (focused on maths) having into account operational delays (I/O availability policies) and timeouts. 我一直在处理javascript动画,并且有许多js库(专注于数学),考虑到操作延迟(I / O可用性策略)和超时。

In your first code snippet, you have these operations: 在您的第一个代码段中,您有以下操作:

$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').css("transition", "transform 3s linear");

Transform 转变

Css Transform method uses matrix based operations which have a high computational cost. Css变换方法使用具有高计算成本的基于矩阵的运算。 There are css-animation frameworks that do use the graphics processor unit (having matrix operators) which works several times faster to achieve smooth, real-time graphic operations. 有一些css动画框架使用图形处理器单元(具有矩阵运算符),其工作速度快几倍,以实现平滑,实时的图形操作。

Transition 过渡

Css Transition is another graphical operation, but does not modify the css entity with a pure [matrix op matrix] transformation, it uses a right 1-dimension operator, that means your css matrix is modified with an [matrix op array] . Css Transition是另一种图形操作,但不会使用纯[matrix op matrix]变换修改css实体,它使用正确的1维运算符,这意味着您的css矩阵使用[matrix op array]

Then the linear mode you choose, applies linear interpolation (probably just a few integration operators) on the position of your element. 然后选择线性模式,在元素的位置上应用线性插值(可能只是几个积分运算符)。 It has low computational cost, which makes the whole transition operation still faster to compute. 它具有较低的计算成本,这使得整个转换操作的计算速度更快。

This is a schema of the execution taking place in a sort of timeline: 这是在某种时间轴中执行的执行模式:

transform         calculation-process
exec -----------------------------------------> applied
 |         |                            |        |
 |         |                            |        |
 |         |                            |        |
transition |     calculation-process    |        |
--------- exec ---------------------> applied --------- 

As jQuery on the top of javascript has non blocking code execution (for i/o depending functions, and unless you code it synch) which is a base of the asynchronous policy of javascript, allows the next operation to execute even before the precedent finishes. 由于javascript顶部的jQuery具有非阻塞代码执行(对于i / o依赖函数,除非你编码同步),这是javascript异步策略的基础,允许在先前完成之前执行下一个操作。

Your fix with the timeout function, ensures that the transform operation is completed before running following code, but as limitation, it will work only for clients with similar computational speed than the current client's processor. 使用超时功能进行修复可确保在运行以下代码之前完成转换操作,但作为限制,它适用于计算速度与当前客户端处理器相似的客户端。 (If you develop it in a pc, then it might fail in a smartphone) (如果你在电脑上开发它,那么智能手机可能会失败)

Another solution I use in my code is to use the jquery callbacks. 我在代码中使用的另一个解决方案是使用jquery回调。 Have a look at the jquery animate() doc in which is shown: 看一下jquery animate() doc ,其中显示了:

.animate( properties [, duration ] [, easing ] [, complete ] ) .animate(properties [,duration] [,easing] [,complete])

In your example it would be something like: 在您的示例中,它将类似于:

$('.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)");
});

I found many useful libs around to "seriously" play with animations. 我找到了很多有用的库,可以“认真地”使用动画。 These are some of the libs I use: 这些是我使用的一些库:

d3.js d3.js
bounce.js bounce.js
secuence.js secuence.js
paper.js paper.js

I hope it helps. 我希望它有所帮助。

Update 更新
There is a good SO answer about animate and css transitions here . 关于动画和css过渡在这里有一个很好的答案。

I think that there are some great answers here telling you why it does work, but if you want a more browser supported animation, use jQuery animations . 我认为这里有一些很好的答案告诉你它为什么会起作用,但是如果你想要一个更多浏览器支持的动画,请使用jQuery animations

$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 eg 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 的jsfiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM