我想做什么(坏了(:
<div></div>
<button>go</button>
$('button').click(function () {
$('div').css({
'transition': 'left 1000ms'
}).addClass('left').addClass('left_more');
});
http://jsfiddle.net/0bm4wq7h/13/
还是坏了:
<div></div>
<button>go</button>
$('button').click(function () {
$('div').css({
'transition': 'left 1000ms'
}).addClass('left');
console.log('test');
$('div').addClass('left_more');
});
http://jsfiddle.net/fwL3dwz2/3/
但这有效:
<div></div>
<button>go</button>
$('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才进行转换?
更新:
所以我接受了斯特里纳的回答,因为它对我有用,现在我又遇到了同样的问题。上面的代码是这个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
类:
#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');
我正在使用铬:
Version 45.0.2454.101 Ubuntu 14.04 (64-bit)
更新
它不起作用的示例:http://jsfiddle.net/me8ukkLe/12/
当它调用$('div').css('left')
时,你的转换在情况三下有效,因为jQuery将调用该方法window.getComputedStyle
(或一个非常相似的方法,取决于浏览器兼容性问题(。在 Tim Taubert(Mozilla 员工(的一篇博客文章中,描述了这个技巧:
getComputedStyle()
与访问属性值结合使用 实际上刷新所有挂起的样式更改并强制布局 引擎来计算我们<div>
的当前状态。
如果不强制重新计算布局,重新计算将延迟到两个类(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/
已发布的第二个方案与已发布的第 3 个方案:
尽管这两个示例都没有为div
定义left
属性,但与第二个场景相比,第三个场景之所以有效是因为console.log
造成的延迟。
在第一条声明中,
$('div').css({
'transition': 'left 1000ms'
}).addClass('left');
class
left
将添加到 div
元素中,该元素在内部添加 left
属性。但是添加控制台.log($('div'(.css('left'(会调用window.getComputedStyle(如Stryner所提到的(,它注册计算值并添加$('div').addClass('left_more');
基本上给了它一个从left : 100px
到left : 600px
的转换的机会。
好问题!这种行为乍一看确实很奇怪。清楚地解释这一点也有点棘手,但首先,请了解以下内容:
1(Javascript函数原子执行
在 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 条信息,一条是css
值,另一条是class
值。这与另一个示例形成对比,其中函数运行后只剩下一条信息:class
值。
如果您只想使用类,并且仍然进行转换,则流程必须如下所示:
1( 添加left
类2(退出功能,允许浏览器查看状态3( 添加left_more
类
为作文而战,哈哈。但我认为这需要很长的解释,因为这个问题很微妙。
这里有几个问题。在给出的示例中,添加第一个left
类时不会发生转换的原因是,为了使呈现引擎对属性进行动画处理,该属性需要已经具有值。在这种情况下,left
没有值,因此不会发生转换。
链接时它不起作用的原因是因为特异性。 jQuery将添加这两个类,当调用呈现页面时,由于它们共享的特殊性,将应用最后添加的左侧定义。
它似乎可以通过在单独的时间添加类而不是链接来工作的原因是,当控制台访问元素的 css 值时.log渲染引擎是从 jQuery 隐式调用的。斯特里纳在这里的回答中指出了这一点:https://stackoverflow.com/a/33902053/1026459。这是一个非常好的发现。
下面是一个应用的示例,以便不需要猜测 left 的值。
发生的事情的实质是发现元素的偏移量以获得左侧的像素偏移量。然后,该值将应用于左侧样式属性。此时,当元素仍未更改位置时,将调用呈现引擎来更新 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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>go</button>