我想做什么(破解):
<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之前不会进行转换?
所以我接受了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
班级:
#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/
答案 0 :(得分:4)
当调用$('div').css('left')
时,你的转换工作在第三种情况,因为jQuery将调用方法window.getComputedStyle
(或者一种非常类似的方法,具体取决于浏览器兼容性问题)。在Tim Taubert(Mozilla员工)的a blog post中,描述了这个技巧:
getComputedStyle()
与访问属性值相结合 实际上刷新所有挂起的样式更改并强制布局 引擎来计算我们<div>
的当前状态。
在不强制进行此布局重新计算的情况下,重新计算会延迟到添加两个类(left
和left-more
)之后,这将计算其在400px
处的位置。
Example Fiddle - 使用getComputedStyle
并访问.left
答案 1 :(得分:1)
“CSS3过渡允许您在给定的持续时间内平滑地(从一个值到另一个值)更改属性值。”
发布第一个场景:
为了使css
转换起作用,您需要为要进行转换的元素指定css
属性。在您的示例中,您正在对left
属性进行转换,但它的初始值未在div css
中定义。
要修复它,只需添加left
属性。
div {
position: absolute;
width: 10px;
height: 10px;
background-color: red;
left: 0px;
}
工作示例:http://jsfiddle.net/0bm4wq7h/14/
发布的第二个方案与第三个方案发布:
尽管两个示例都没有为left
定义div
属性,但第3个场景与第2个场景相比有效的原因是{{1}引起的延迟}。
在第一个声明中,
console.log
$('div').css({
'transition': 'left 1000ms'
}).addClass('left');
class
已添加到left
元素,该元素在内部添加div
属性。但添加console.log($('div')。css('left')调用window.getComputedStyle(如Stryner所述),它注册计算值并添加left
基本上给它一个机会来执行从$('div').addClass('left_more');
过渡到left : 100px
。
答案 2 :(得分:0)
好问题!这个行为一开始看起来很怪异。要清楚地解释这一点也有点棘手,但首先要了解以下内容:
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
class,但由于没有初始左值,因此没有动画。 (css级联;当两个类都存在时,left_more
完全覆盖left
)
小提琴2
同样的问题 - 在浏览器处理它之前覆盖left
类
小提琴3
这是因为通过调用css
来设置值,然后不会覆盖,因为addClass
用于设置值应该设置为动画的位置。 console.log
无关紧要 - 所有重要的是css
函数调用。该函数完成后,有2条信息,1条为css
值,另一条为class
值。这与另一个示例形成鲜明对比,在该示例中,函数运行后只剩下一个信息:class
值。
如果您只想使用类,并且仍然可以进行转换,则流程必须如下所示:
1)添加left
课程
2)退出功能,允许浏览器查看状态
3)添加left_more
类
Sry for the eleay lol。但我认为这需要一个很长的解释,因为这个问题很微妙。
答案 3 :(得分:0)
这里有几个问题。在给出的示例中,添加第一个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');
});
&#13;
button {
margin-top: 30px;
}
div {
position: absolute;
width: 10px;
height: 10px;
background-color: red;
}
.left {
left: 100px;
}
.left_more {
left: 400px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>go</button>
&#13;