jQuery addClass方法链接以执行CSS转换

时间:2015-11-24 18:50:31

标签: jquery css css-transitions

我想做什么(破解):

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

4 个答案:

答案 0 :(得分:4)

当调用$('div').css('left')时,你的转换工作在第三种情况,因为jQuery将调用方法window.getComputedStyle(或者一种非常类似的方法,具体取决于浏览器兼容性问题)。在Tim Taubert(Mozilla员工)的a blog post中,描述了这个技巧:

  

getComputedStyle()与访问属性值相结合   实际上刷新所有挂起的样式更改并强制布局   引擎来计算我们<div>的当前状态。

在不强制进行此布局重新计算的情况下,重新计算会延迟到添加两个类(leftleft-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

&#13;
&#13;
$('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;
&#13;
&#13;