我正在创建一个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;
}
我是不是搞砸了,还是"一气呵成"不是应该做的事情?
我们非常感谢所有的帮助。
一种不依赖于setTimeout的更干净的方法是在设置之前读取有问题的css属性:
var div = $('<div />').addClass('trans');
$('#container').append(div);
div.css('width');//add this line
div.css('width', '200px');
在这里工作:
var div = $('<div class="trans" />');
$('#container').append(div);
var div = $('<div />').addClass('trans');
$('#container').append(div);
div.css('width');//add this line
div.css('width', '200px');
.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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container"></div>
正如Lucero在下面的评论中所解释的那样,这样做有必要迫使浏览器计算实际值,而不是";"自动"inherit";或类似的。如果没有实际值,浏览器将不知道新值是对以前值的更改。
这里有两种方法。
1-CSS转换
通过使用setTimeout
,addClass
方法将在之后运行,而不是与前面的脚本一起运行,这样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;
}
尝试调用jQuery的.offset()
方法。
当浏览器获得偏移量时,它会触发一个回流/重新绘制/布局事件,从而允许转换工作。
看看这把小提琴:http://jsfiddle.net/FYPpt/199/
另请参阅--http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
响应赏金:
如果你不知道哪个属性正在转换,或者只是认为强制setTimeout
启动动画不是一个好做法,你可以用另一种方式强制回流。
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因触发多个reflow而臭名昭著(,但在将类似的解决方案添加到整个网站之前,仍然需要考虑一些问题。
重要提示:这与setTimeout
调用相比效率不高也不低。这不是一个灵丹妙药的解决方案,它在幕后做着同样的事情。
以下是相应的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;
}
正如@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感到兴奋。在new-rules
的CSS文件中更改:(
http://jsfiddle.net/FYPpt/201/
var div = $('<div />');
$('#container').append(div);
div.css('width', '20px').addClass('trans', function() {
div.css('width', '200px')
});
创建一个新的DIV元素,并将trans类添加到该元素中,以激发CSS转换