joe*_*ews 64 javascript css dom css3
正如这个问题所观察到的那样,新添加的元素上的立即CSS转换以某种方式被忽略 - 转换的结束状态立即呈现.
例如,给定此CSS(此处省略前缀):
.box {
opacity: 0;
transition: all 2s;
background-color: red;
height: 100px;
width: 100px;
}
.box.in { opacity: 1; }
Run Code Online (Sandbox Code Playgroud)
此元素的不透明度将立即设置为1:
// Does not animate
var $a = $('<div>')
.addClass('box a')
.appendTo('#wrapper');
$a.addClass('in');
Run Code Online (Sandbox Code Playgroud)
我已经看到了几种触发转换以获得预期行为的方法:
// Does animate
var $b = $('<div>')
.addClass('box b')
.appendTo('#wrapper');
setTimeout(function() {
$('.b').addClass('in');
},0);
// Does animate
var $c = $('<div>')
.addClass('box c')
.appendTo('#wrapper');
$c[0]. offsetWidth = $c[0].offsetWidth
$c.addClass('in');
// Does animate
var $d = $('<div>')
.addClass('box d')
.appendTo('#wrapper');
$d.focus().addClass('in');
Run Code Online (Sandbox Code Playgroud)
相同的方法适用于vanilla JS DOM操作 - 这不是特定于jQuery的行为.
编辑 - 我正在使用Chrome 35.
JSFiddle(包括vanilla JS示例).
Fri*_*izi 104
不动画新添加的元素的原因是浏览器批处理重排.
添加元素时,需要回流.这同样适用于添加类.但是当你在单个javascript循环中同时执行这两个操作时,浏览器会有机会优化第一个.在这种情况下,只有单个(初始和最终同时)样式值,因此不会发生转换.
这个setTimeout技巧有效,因为它将类添加延迟到另一个javascript循环,因此渲染引擎存在两个值,需要计算,因为有时间点,当第一个呈现给用户时.
批处理规则还有另一个例外.如果您尝试访问它,浏览器需要计算立即值.其中一个值是offsetWidth.当您访问它时,将触发重排.另一个在实际显示期间单独完成.同样,我们有两个不同的样式值,因此我们可以及时插入它们.
当这种行为是可取的时,这实际上是极少数情况之一.大多数时候,在DOM修改之间访问引起回流的属性会导致严重的减速.
首选解决方案可能因人而异,但对我而言,offsetWidth(或getComputedStyle())的访问是最好的.有些情况下,在setTimeout没有样式重新计算的情况下被解雇.这是罕见的情况,主要是在加载的网站上,但它发生了.那你就不会得到你的动画了.通过访问任何计算的样式,您强制浏览器实际计算它.
The*_*pha 28
使用jQuery试试这个(这里的例子):
var $a = $('<div>')
.addClass('box a')
.appendTo('#wrapper');
$a.css('opacity'); // added
$a.addClass('in');
Run Code Online (Sandbox Code Playgroud)
使用Vanilla javaScript试试这个:
var e = document.createElement('div');
e.className = 'box e';
document.getElementById('wrapper').appendChild(e);
window.getComputedStyle(e).opacity; // added
e.className += ' in';
Run Code Online (Sandbox Code Playgroud)
简要说明:
该的getComputedStyle()刷新所有悬而未决的风格变化,迫使布局引擎来计算元素的当前状态,因此 的.css()的工作原理类似的方式.
关于css()从jQuery网站:
.css()方法是从第一个匹配元素获取样式属性的便捷方法,特别是考虑到浏览器访问大多数这些属性的不同方式(基于标准的浏览器中的getComputedStyle()方法与currentStyle和runtimeStyle Internet Explorer中的属性)以及浏览器用于某些属性的不同术语.
您可以使用getComputedStyle()/css()而不是setTimeout.您也可以阅读本文以获取一些详细信息和示例.
请使用以下代码,使用"focus()"
var $a = $('<div>')
.addClass('box a')
.appendTo('#wrapper');
$a.focus(); // focus Added
$a.addClass('in');
Run Code Online (Sandbox Code Playgroud)
var e = document.createElement('div');
e.className = 'box e';
document.getElementById('wrapper').appendChild(e).focus(); // focus Added
e.className += ' in';
Run Code Online (Sandbox Code Playgroud)
@Frizi的解决方案有效,但有时我发现getComputedStyle当我更改某个元素的某些属性时,它无效.如果这不起作用,你可以尝试getBoundingClientRect()如下,我发现它是防弹的:
假设我们有一个元素el,在这我们要转型opacity,但是el是display:none; opacity: 0:
el.style.display = 'block';
el.style.transition = 'opacity .5s linear';
// reflow
el.getBoundingClientRect();
// it transitions!
el.style.opacity = 1;
Run Code Online (Sandbox Code Playgroud)
我更喜欢 requestAnimationFrame + setTimeout(见这篇文章)。
const child = document.createElement("div");
child.style.backgroundColor = "blue";
child.style.width = "100px";
child.style.height = "100px";
child.style.transition = "1s";
parent.appendChild(child);
requestAnimationFrame(() =>
setTimeout(() => {
child.style.width = "200px";
})
);
Run Code Online (Sandbox Code Playgroud)
在这里试试。
(如果您绝对不想在初始节点上使用这些动画,请添加另一个类.initial抑制动画)
function addNode() {
var node = document.createElement("div");
var textnode = document.createTextNode("Hello");
node.appendChild(textnode);
document.getElementById("here").appendChild(node);
}
setTimeout( addNode, 500);
setTimeout( addNode, 1000);Run Code Online (Sandbox Code Playgroud)
body, html { background: #444; display: flex; min-height: 100vh; align-items: center; justify-content: center; }
button { font-size: 4em; border-radius: 20px; margin-left: 60px;}
div {
width: 200px; height: 100px; border: 12px solid white; border-radius: 20px; margin: 10px;
background: gray;
animation: bouncy .5s linear forwards;
}
/* suppres for initial elements */
div.initial {
animation: none;
}
@keyframes bouncy {
0% { transform: scale(.1); opacity: 0 }
80% { transform: scale(1.15); opacity: 1 }
90% { transform: scale(.9); }
100% { transform: scale(1); }
}Run Code Online (Sandbox Code Playgroud)
<section id="here">
<div class="target initial"></div>
</section>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24299 次 |
| 最近记录: |