25

我正在创建一个 DOM 元素(一个 div),将其添加到 DOM,然后在 javascript 中一键更改其宽度。这在理论上应该触发 CSS3 过渡,但结果是直接从 A 到 B,中间没有过渡。

如果我通过单独的测试点击事件改变宽度,一切都会按预期工作。

这是我的 JS 和 CSS:

JS(jQuery):

var div = $('<div />').addClass('trans').css('width', '20px');
$('#container').append(div);
div.css('width', '200px');

CSS(只是 Mozilla 一分钟):

.trans {
    -moz-transition-property: all;
    -moz-transition-duration: 5s;
    height: 20px;
    background-color: cyan;
}

我在这里搞砸了,还是“一击即中”不是应该做的事情?

非常感谢所有帮助。

4

6 回答 6

48

一种不依赖于 setTimeout 的更简洁的方法是在设置之前读取有问题的 css 属性:

var div = $('<div />').addClass('trans');
$('#container').append(div);
div.css('width');//add this line
div.css('width', '200px');

在这里工作:

http://jsfiddle.net/FYPpt/144/

正如 Lucero 在下面的评论中所解释的那样,这样做有必要强制浏览器计算实际值,而不是“自动”、“继承”或类似的值。如果没有实际值,浏览器将不知道新值是对先前值的更改。

于 2013-11-11T13:44:15.863 回答
21

这里有两种方法可以做到这一点。

1 - CSS 过渡

通过使用setTimeoutaddClass方法将在之后运行而不是与前面的脚本一起运行,以便transition触发事件

示例 jsfiddle

jQuery:

var div = $('<div class="trans" />');
$('#container').append(div);
// set the class change to run 1ms after adding the div
setTimeout(function() {div.addClass('wide')}, 1); 

CSS:

.trans {
    width: 20px;
    height: 20px;
    background-color: cyan;
    -webkit-transition: all 5s ease;
       -moz-transition: all 5s ease;
        -ie-transition: all 5s ease;
         -o-transition: all 5s ease;
            transition: all 5s ease;
}
.wide {
    width: 200px;
}

2 - jQuery的.animate()功能

示例 jsfiddle

jQuery:

var div = $('<div class="trans" />');
$('#container').append(div);
div.animate({'width': '200px'}, 5000); // 5 sec animation

CSS:

.trans {
    width: 20px;
    height: 20px;
    background-color: cyan;
}
于 2011-08-15T20:13:29.183 回答
6

尝试调用 jQuery 的.offset()方法。

当浏览器获得偏移量时,它会触发一个允许转换工作的回流/重绘/布局事件。

看到这个小提琴:http: //jsfiddle.net/FYPpt/199/

另见——http: //gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html

于 2014-12-10T15:39:39.107 回答
4

回应赏金:

如果您不知道正在转换哪个属性,或者根本不认为强制 asetTimeout触发动画是一个好习惯,您可以通过另一种方式强制回流。

首先起作用的原因setTimeout是由于您同时导致整个文档重排,即使持续时间设置为0. 这不是导致回流的唯一方法。


链接到小提琴

JavaScript

for (x = Math.ceil(Math.random() * 10), i=0;i<x;i++){
    $('<div />').appendTo($('#container')).addClass('trans');
}

var divs = $('#container div');
var x = divs.eq(Math.ceil(Math.random() * divs.length));
x[0].offsetHeight;
x.addClass('wide');

使用这个 JavaScript,我们随机添加 1 到 10 个div元素,然后随机选择其中一个并添加wide类。

您会注意到其中有一行奇怪的 JavaScript,即x[0].offsetHeight. 这是整个操作的关键。调用offsetHeight触发文档重排而不使用 setTimeout 或查询 CSS 值。

回流与 DOM 的关系是什么:

回流计算页面的布局。元素上的重排会重新计算元素的尺寸和位置,并且还会触发该元素的子元素、祖先元素和出现在 DOM 中的元素的进一步重排。然后它调用最终重绘。回流非常昂贵,但不幸的是它很容易触发。

因此,请谨慎使用这些功能。对大多数现代浏览器来说并不太担心(因为 jQuery 因触发多次重排而臭名昭著),但在在您的网站上添加类似此解决方案的内容之前仍然需要考虑一些事情。


重要提示:并不比 setTimeout call效率更高或更低。这不是一个灵丹妙药的解决方案,它在幕后做同样的事情。


这是相应的CSS,供参考:

.trans {
    width: 20px;
    height: 20px;
    background-color: cyan;
    -webkit-transition: all 5s ease;
       -moz-transition: all 5s ease;
         -o-transition: all 5s ease;
            transition: all 5s ease;
}

.trans.wide {
    width: 200px;
}
于 2014-12-11T17:41:09.553 回答
2

正如@onetrickpony 所问的那样,如果所有规则都在 CSS 文件中并且不应该添加到 JS 函数中怎么办。

根据 Torin Finnemann 的回答,稍作改动:

添加一个额外的类,其中定义了规则:new-rules

var div = $('<div class="trans" />');
$('#container').append(div);

var div = $('<div />').addClass('trans');
$('#container').append(div);
div.height();
div.addClass('new-rules');

在您的 CSS 中有预定义的类:

.trans.new-rules {
    width: 200px;
    background: yellow;
}

现在在更改 CSS 时无需对 JS 感到刺痛。在 CSS 文件中更改它new-rules:)

http://jsfiddle.net/FYPpt/201/

于 2014-12-10T18:48:01.707 回答
1
var div = $('<div />');

$('#container').append(div);

div.css('width', '20px').addClass('trans', function() {
   div.css('width', '200px') 
});

创建一个新的 DIV 元素并将“trans”类添加到该元素以触发 CSS 过渡

于 2014-12-12T19:04:57.083 回答