jQuery addClass方法链接以执行CSS转换
我想做什么( 破产 ):
$('button').click(function () { $('div').css({ 'transition': 'left 1000ms' }).addClass('left').addClass('left_more'); });
http://jsfiddle.net/0bm4wq7h/13/
仍然破产 :
$('button').click(function () { $('div').css({ 'transition': 'left 1000ms' }).addClass('left'); console.log('test'); $('div').addClass('left_more'); });
http://jsfiddle.net/fwL3dwz2/3/
但这有效 :
$('button').click(function () { $('div').css({ 'transition': 'left 1000ms' }).addClass('left'); console.log($('div').css('left')); $('div').addClass('left_more'); });
http://jsfiddle.net/j8x0dzbz/5/
我知道我需要一个CSS过渡的起点。 这就是我加left
原因。
为什么jQuery在我的#3之前不会进行转换?
更新:
所以我接受了Stryner的答案,因为它对我有用,现在我又遇到了同样的问题。 上面的代码是这个JavaScript的简化版本:
$('#screen_wrapper img:eq(0)').removeClass().addClass('prep'); //starting point window.getComputedStyle(document.getElementById('photo'+0)).left; //force the the styling to get recomputated using raw JavaScript $('#screen_wrapper img:eq(0)').css('left');//force the the styling to get recomputated using jQuery $('#screen_wrapper img:eq(0)').addClass('animate_in');//animate to the "animate_in" class coordinates from the "prep" class coordinates
发生的事情是我从prep
课前的坐标开始制作动画。
这是prep
class:
#screen_wrapper img.prep { top: 0px; left: 506px; }
但是图像实际上是从这个使用removeClass()
jQuery方法删除的类开始的:
.animate_out { visibility: visible; top: 0px; left: -506px; }
transition
属性正常运行:
$('#screen_wrapper img').css('transition','left 1000ms');
我怀疑这些力量重新计算造型:
window.getComputedStyle(document.getElementById('photo'+0)).left; $('#screen_wrapper img:eq(0)').css('left');
我正在使用Chromium:
Version 45.0.2454.101 Ubuntu 14.04 (64-bit)
更新
它不工作的例子: http : //jsfiddle.net/me8ukkLe/12/
当你调用$('div').css('left')
时,你的转换工作在window.getComputedStyle
因为jQuery将调用window.getComputedStyle
方法(或者一种非常类似的方法,具体取决于浏览器兼容性问题)。 在Tim Taubert(Mozilla员工) 的博客文章中 ,描述了这个技巧:
getComputedStyle()
结合访问属性值实际上刷新所有挂起的样式更改并强制布局引擎计算我们的的当前状态。
在不强制进行此布局重新计算的情况下,重新计算将延迟到添加两个类( left
和left-more
)之后,这将计算其在400px
处的位置。
示例小提琴 – 使用getComputedStyle
并访问.left
“CSS3过渡允许您在给定的持续时间内平滑地(从一个值到另一个值)更改属性值。”
第一个场景发布:
为了使css
转换起作用,您需要为要进行转换的元素指定css
属性。 在您的示例中,您正在对left
属性进行转换,但它的初始值未在div css
定义。
要修复它,只需添加left
属性即可。
div { position: absolute; width: 10px; height: 10px; background-color: red; left: 0px; }
工作示例: http : //jsfiddle.net/0bm4wq7h/14/
发布的第二个情景与第三个情景发布
尽管两个示例都没有为div
定义left
属性,但第三个场景与第二个场景相比的原因是由于console.log
引起的延迟。
在第一个声明中,
$('div').css({ 'transition': 'left 1000ms' }).addClass('left');
class
left
添加到div
元素,在内部添加left
属性。 但添加console.log($(’div’)。css(’left’)会调用window.getComputedStyle(如Stryner所述),它注册计算值并添加$('div').addClass('left_more');
基本上给它一个机会从left : 100px
执行过渡left : 100px
到left : 600px
。
好问题! 这个行为一开始看起来很怪异。 解释清楚这一点也有点棘手,但首先要了解以下内容:
1)Javascript函数以primefaces方式执行
在JS中,函数总是从头到尾运行,而不会在中途发生任何其他操作。 这与说JS是单线程语言是一样的 。
2)浏览器也不能中断javascript
JS代码不仅无法在函数中途运行,而且代码运行的浏览器选项卡也不会插入! 这意味着当JS函数运行时,网页上的(几乎)所有内容都会停止(重绘,动画,样式表应用程序等)。 如果你想测试这个,你可以尝试运行while (true) { var i = 'yo'; }
在控制台中。 (警告:这会让你难过)
3)JS函数内部的状态对于浏览器是不可见的
因为浏览器不能在JS函数中间中断,这意味着浏览器永远不会知道在所述函数中途发生的任何状态。 浏览器只能根据函数完成后保留的状态进行操作。 不清楚? 为了显示:
var someGlobalValue = null; function lol() { someGlobalValue = 'hi'; someGlobalValue = 'hello'; someGlobalValue = 'ok'; }
当运行函数lol
, someGlobalValue
假设多个值,但浏览器只会知道最后一个值 ,因为它必须在中途插入才能看到其他值(它不能做!)
4)JS函数内部的CSS状态同样对浏览器不可见
这同样适用于css状态! (现在你可能会发现我实际上已经开始回答你的问题了)。
如果您调用以下函数:
function lol() { $('.thing').css('left', '10px'); $('.thing').css('left', '30px'); }
浏览器永远不会应用left: 10px
值,因为它不会在函数中途执行任何操作! 浏览器只能处理函数的结果,一个完整的结果。
回答你的问题!!
小提琴1
left_more
类在left
类后立即添加 – 浏览器永远不会看到left
类,并在函数结束后应用css样式 – 应用left_more
类,但由于没有初始左值存在,因此没有动画。 (css级联;当两个类都存在时, left_more
完全覆盖left
)
小提琴2
同样的问题 – 在浏览器处理之前,会覆盖left
类
小提琴3
这是因为该值是通过调用css
,然后不会被覆盖,因为addClass
用于设置值应该设置为动画的位置。 console.log
是无关紧要的 – 所有重要的是css
函数调用。 一旦该函数完成,就有2条信息,1条是css
值,另一条是class
值。 这与另一个例子形成鲜明对比,在该例子中,函数运行后只剩下一条信息: class
值。
如果您只想使用类,并且仍然可以进行转换,则流程必须如下所示:
1)添加left
类2)退出function, 允许浏览器查看状态 3)添加left_more
类
Sry for the essay哈哈。 但我认为这需要一个很长的解释,因为问题的微妙之处。
这里有几个问题。 在给出的示例中,添加第一个left
类时不发生转换的原因是因为为了使呈现引擎为属性设置动画,该属性需要已经具有值。 在这种情况下, left
没有值,因此不会发生转换。
链接时不起作用的原因是因为特异性。 jQuery将添加这两个类,并且当进行呈现页面的调用时,由于它们的共享特性,应用了左边的最后添加的定义。
之所以在单独的时间添加类而不是链接的原因是因为当console.log访问元素的css值时,从jQuery隐式调用了渲染引擎。 Stryner在答案中指出了这一点: https ://stackoverflow.com/a/33902053/1026459。 这是一个非常好的发现。
下面是一个应用示例,以便不需要猜测左边的值。
发生的事情是找到元素的偏移量以获得左边的像素偏移量。 然后将该值应用于左样式属性。 此时元素仍然没有改变位置,调用渲染引擎来更新left属性。 然后删除该属性以确保特异性不优先于类定义,然后应用类定义。 这将有助于第一次遭遇的过渡。
jsFiddle Demo
$('button').click(function() { $('div').css({'transition':'left 1000ms'}).each(function(){ $(this).css('left',$(this).offset().left); window.getComputedStyle(this,null).getPropertyValue("left"); }).css('left','').addClass('left'); });
button { margin-top: 30px; } div { position: absolute; width: 10px; height: 10px; background-color: red; } .left { left: 100px; } .left_more { left: 400px; }