绕过转换并立即更改属性

我想绕过CSS转换并立即更改属性。
我尝试在更改之前将transition-duration设置为0s ,然后将transition-duration设置回原始值:

 $('div').css('width', '200px').delay(1000).queue(function() { $(this).css({ transitionDuration: '0s', msTransitionDuration: '0s', mozTransitionDuration: '0s', webkitTransitionDuration: '0s', oTransitionDuration:'0s' }).css('width', '10px').css({ transitionDuration: '2s', msTransitionDuration: '2s', mozTransitionDuration: '2s', webkitTransitionDuration: '2s', oTransitionDuration:'2s' }) })​ 

小提琴
这显然不起作用。

我知道规范没有为此定义该行为:

由于此规范未定义计算值何时更改,因此计算值的哪些更改被同时考虑,因此作者应注意在进行可能转换的更改后,在少量时间内更改任何转换属性可能会导致行为实现之间有所不同,因为在某些实现中可能会同时考虑这些更改,

是否有捷径可寻?

注意:我正在更改的属性是transform所以.animate()不是一个选项。

由于没有其他人发布有效答案,这里有:

 $('div').css('width', '200px').delay(1000).queue(function() { $(this).css({transition: '0s', width: '10px'}).delay(1).queue(function() { $(this).css({transition:'2s'}); }); },1000)​; 

小提琴

或者如果是另一种方式:

 $('div').css({ transition: '0s' }).css('width', '200px').delay(1000).queue(function() { $(this).css({width: '10px', transition: '2s'}); }); 

小提琴

jQuery应该规范化供应商前缀这些天,所以你不必自己键入它们。


这里的问题是jQuery一次性附加所有样式,只保留最后的样式,覆盖相同CSS属性的先前样式而不用重新绘制DOM,并且使用本机javascript进行测试似乎也在做同样的事情,因此,可能是浏览器试图通过添加样式来避免不必要的回流,只是为了在下一行代码中更改它,所以这样做:

 $('div').css({ transition: '0s', width: 200 }).css({ transition: '3s', width: 10 }); 

将不起作用,因为只添加了最后一个样式。

这就是delay()发挥作用的地方,OP的问题已经在使用delay()所以没有理由不使用它,但删除delay()当然会导致上述问题,浏览器不会绘制第一种风格,但只有最后一种

由于delay()实际上只是一个花哨的超时,它实际上推迟了第二个样式设置的执行,导致两个浏览器重新绘制。

由于这很可能是一个浏览器问题,而不是我们可以改变的东西,推迟第二种风格的设置是使这项工作的唯一方法,即使设置为仅1毫秒,或使用延迟,使用延迟仍然有效可以通过常规超时推迟执行,这是推迟执行脚本的常用方法:

 $('div').css({ transition: '0s', width: 200 }); setTimeout(function() { $('div').css({ transition: '3s', width: 10 }); }); 

小提琴

上面的工作正常,因为超时会导致浏览器绘制样式的第一个设置,并将超时内的样式设置延迟到以后的时间,但是由于没有设置时间,所以很快就会执行因为浏览器可以(但仍然推迟到当前脚本完成之后),这对于人眼来说似乎是立即的,并且解决了这个问题。

如果你有CSS的控制权

最简单的方法是将动画绑定到某个类,然后在什么时候想要不再绕过动画,添加类,否则不会设置任何动画。 如果相反,您通常需要动画,但偶尔想要绕过它,然后默认添加该类并在绕过时将其删除。

示例CSS

 div{ height: 100px; width: 200px; background: red; } div.doTransition { width: 10px; transition: width 2s linear; -ms-transition: width 2s linear; -moz-transition: width 2s linear; -webkit-transition: width 2s linear; -o-transition: width 2s linear; } 

请参阅创建点击事件以在需要时启动动画的小提琴 ,但这可能是在不再想要绕过它时添加类的其他程序触发器。 这个小提琴正好相反 ,它假定动画存在,但在页面加载时立即通过删除类来绕过它。

设置一个覆盖类,它将禁用应用于的元素上的css转换, !important对此非常适合:

 .notransition { -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; -ms-transition: none !important; transition: none !important; } 

您现在可以使用toggleClass切换所需的行为(平滑过渡与即时更改):

 $('div'). toggleClass('notransition', true). //or false! css('width', '200px'); 

摆弄 。 IMO这种方法的一个优点是你可以清楚地分离默认元素样式和禁用所有平滑动画标志。 这也是一种非常“可重复”的可重用方法,即您可以轻松地向现有方法添加可选的布尔属性,以指示是否应该使用转换执行它。

注意:有时您可能希望在出于性能/用户体验原因的情况下完全禁用页面上的转换。 在这种情况下,您可以将选择器更改为.notransition *并禁用所有后代元素的转换。

问题在于,由于浏览器没有理由单独放慢速度并执行每个操作,因此它将它们组合在一起并同时执行。 查询offsetHeight是强制它单独执行每个操作的一种方法,因为它必须重新计算高度。 http://jsfiddle.net/markasoftware/6cTeY/15/完美无缺

这是我能让它发挥作用的唯一方法。 jQuery似乎有点顽固。

http://fiddle.jshell.net/8qTpe/1/

PS您的方法有一些错误:

  1. 您在延迟之前重新resize为200px,因此使用默认的CSS设置。

  2. 在将转换更改回2s之前,您将重新resize为10px。

现在jQuery似乎连续应用了所有CSS设置,这就是为什么整件事似乎不起作用。

我会选择一个相当干净的CSS解决方案

HTML

 

JS

 $('button.out').click(function(){console.log($('#foo').addClass);$('#foo').addClass('out')}) $('button.in').click(function(){$('#foo').removeClass('out')}) 

CSS

 div{ height: 100px; width: 10px; background: red; transition: width 0s linear; -ms-transition: width 0s linear; -moz-transition: width 0s linear; -webkit-transition: width 0s linear; -o-transition: width 0s linear; } div.out { width: 200px; transition: width 2s linear; -ms-transition: width 2s linear; -moz-transition: width 2s linear; -webkit-transition: width 2s linear; -o-transition: width 2s linear; } 

http://jsfiddle.net/6cTeY/19/

我通常以这种香草JS的方式来做。

小提琴

HTML

假设你有一个元素

 

CSS

假设您的元素已经激活了CSS Transitions并且background:green

 #element { background: green; width: 200px; height: 200px; -webkit-transition: 'all 0.5s ease-out'; -moz-transition: 'all 0.5s ease-out'; -ms-transition: 'all 0.5s ease-out'; -o-transition: 'all 0.5s ease-out'; } 

JS

该元素具有CSS过渡,但我们想立即将元素的背景更改为BLUE。

在此之后,我们希望元素的正常行为返回,以便我们可以将其背景设置为RED。

我们需要暂时关闭转换并立即恢复它们。

 // grab the element var element = document.getElementById('element'); // removeTransitions element.style.webkitTransition = 'none'; element.style.mozTransition = 'none'; element.style.msTransition = 'none'; element.style.oTransition = 'none'; // apply desired 'instant' property element.style.background = 'blue'; // is applied instantly // this 10ms timeout is necessary for the transitions to be active again setTimeout(function() { element.style.webkitTransition = 'all 5s ease-out'; element.style.mozTransition = 'all 5s ease-out'; element.style.msTransition = 'all 5s ease-out'; element.style.oTransition = 'all 5s ease-out'; // apply desired 'animated' property element.style.background = 'red'; // is applied smoothly }, 10); 
 var ball = document.querySelector('.ball'), ballSpeed = 2, button = document.querySelector('button'); // Chane to random speed "instantly" (on button "click") button.addEventListener('click', ()=>{ ballSpeed = Math.random()*8 + 1; ball.style.transitionDuration = ballSpeed + 's'; ball.classList.remove('move'); ball.clientHeight; // <--- triggers repaint ball.classList.add('move'); // set button text button.textContent = ballSpeed.toFixed(2) + 's'; }) function animate( speed ){ ball.style.transitionDuration = '0s'; ball.classList.remove('move'); ball.clientHeight; // <--- triggers repaint. has to be after "move" class was removed ball.style.transitionDuration = ballSpeed + 's'; ball.classList.add('move'); ball.removeEventListener('transitionend', animate) ball.addEventListener('transitionend', animate); // keep rollin.. } animate(); 
 html, body{ height:100%; overflow:hidden; } .ball{ position: absolute; width: 3em; height: 3em; left:0; right:0; top:0; bottom:0; margin: auto; transition-duration: 2s; /* <-- start speed */ transition-timing-function: linear; } .ball::after{ content: ''; display: block; width: 100%; height: 100%; transform: translateX(100%); border-radius:50%; background: gold; } .ball.move{ transform: rotate(360deg); }