Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在附加元素上触发CSS转换_Javascript_Css_Dom - Fatal编程技术网

Javascript 在附加元素上触发CSS转换

Javascript 在附加元素上触发CSS转换,javascript,css,dom,Javascript,Css,Dom,正如所观察到的,新附加元素上的即时CSS转换在某种程度上被忽略了——转换的结束状态被立即呈现 例如,给定此CSS(此处省略前缀): 此元素的不透明度将立即设置为1: // Does not animate var $a = $('<div>') .addClass('box a') .appendTo('#wrapper'); $a.addClass('in'); //不设置动画 变量$a=$('') .addClass('框a') .appendTo(“#wrap

正如所观察到的,新附加元素上的即时CSS转换在某种程度上被忽略了——转换的结束状态被立即呈现

例如,给定此CSS(此处省略前缀):

此元素的不透明度将立即设置为1:

// Does not animate
var $a = $('<div>')
    .addClass('box a')
    .appendTo('#wrapper');
$a.addClass('in');
//不设置动画
变量$a=$('')
.addClass('框a')
.appendTo(“#wrapper”);
$a.addClass('in');
我已经看到了几种触发转换以获得预期行为的方法:

// 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');
//是否设置动画
变量$b=$('')
.addClass('框b')
.appendTo(“#wrapper”);
setTimeout(函数(){
$('.b').addClass('in');
},0);
//有生气吗
变量$c=$('')
.addClass('框c')
.appendTo(“#wrapper”);
$c[0]。offsetWidth=$c[0]。offsetWidth
$c.addClass('in');
//有生气吗
变量$d=$('')
.addClass('框d')
.appendTo(“#wrapper”);
$d.focus().addClass('in');
同样的方法也适用于普通的JSDOM操作——这不是特定于jQuery的行为

编辑-我正在使用Chrome 35

(包括示例)

  • 为什么附加元素上的即时CSS动画会被忽略
  • 这些方法如何以及为什么起作用
  • 还有其他的方法吗
  • 哪种(如果有的话)是首选解决方案?

使用
jQuery
试试这个():

简要想法:

刷新所有挂起的样式更改和 强制布局引擎计算元素的当前状态,因此 类似的工作方式

关于
css()
来自
jQuery
网站:

.css()方法是从 第一个匹配元素,特别是根据不同的方式 浏览器可以访问这些属性中的大部分() 基于标准的浏览器中的方法与and Internet Explorer中的runtimeStyle属性)和不同的术语 浏览器用于某些属性


您可以使用
getComputedStyle()/css()
而不是
setTimeout
。您还可以阅读一些详细信息和示例。

没有为新添加的元素设置动画的原因是浏览器批处理回流

当添加元件时,需要回流。这同样适用于添加类。然而,当您在单轮javascript中同时执行这两项操作时,浏览器会抓住机会对第一轮进行优化。在这种情况下,只有一个(同时是初始和最终)样式值,因此不会发生转换

setTimeout
技巧很有效,因为它会将类添加延迟到另一轮javascript中,因此呈现引擎中有两个值需要计算,因为当第一个值呈现给用户时,存在时间点

批处理规则还有一个例外。如果您试图访问即时值,浏览器需要计算即时值。其中一个值是
offsetWidth
。当您访问它时,会触发回流。另一个是在实际显示期间单独完成的。同样,我们有两个不同的样式值,因此我们可以及时对它们进行插值

这真的是极少数情况下,当这种行为是可取的。大多数情况下,在DOM修改之间访问导致回流的属性会导致严重的速度减慢


首选的解决方案可能因人而异,但对我来说,访问
offsetWidth
(或
getComputedStyle()
)是最好的。在某些情况下,
setTimeout
在没有重新计算样式的情况下被激发。这是一种罕见的情况,大多数情况下发生在加载的站点上,但这种情况确实发生了。那么你就不会得到你的动画了。通过访问任何计算的样式,您就是在强迫浏览器实际计算它。

请使用下面的代码,使用“focus()

滑动分页
我没有试图强制立即重新绘制或计算样式,而是尝试使用
requestAnimationFrame()
允许浏览器在其下一个可用帧上绘制

在Chrome+Firefox中,浏览器对渲染进行了太多优化,因此这仍然没有帮助(适用于Safari)

我决定使用
setTimeout()
手动强制延迟,然后使用
requestAnimationFrame()
负责任地让浏览器绘制。如果在超时结束之前没有绘制附加,动画可能会被忽略,但它似乎工作可靠

setTimeout(function () {
    requestAnimationFrame(function () {
        // trigger the animation
    });
}, 20);

我选择20ms是因为它大于1帧,每秒60帧(16.7ms),而且一些浏览器不会注册超时@Frizi的解决方案是有效的,但有时我发现当我更改某个元素的某些属性时,
getComputedStyle
不起作用。如果这不起作用,您可以按如下方式尝试
getBoundingClientRect()
,我发现这是防弹的:

假设我们有一个元素
el
,我们想在其上转换
opacity
,但是
el
display:none;不透明度:0

el.style.display = 'block';
el.style.transition = 'opacity .5s linear';

// reflow
el.getBoundingClientRect();

// it transitions!
el.style.opacity = 1;

编辑:原始答案中使用的技巧,在水平规则下,没有100%的时间起作用,如注释中所述。

目前,如果使用
requestAnimationFrame()
,可能是最好的,如InPomber的回答所示。自从pomber回复后,这篇文章已经更新,现在它提到了Chrome标志后面的内容

requestPostAnimationFrame()
在所有主要浏览器中达到稳定状态时,这可能会可靠地工作:

const div=document.createElement(“div”);
文件.正文.附件(div);
requestPostAnimationFrame(()=>div.className=“fade”)
div{
高度:100px;
宽度:100px;
背景色:红色;
}
.褪色{
不透明度:0;
过渡:不透明度2s;

}
我更喜欢requestAnimationFrame+setTimeout(请参阅)

试试看。

setTimeout()
仅在竞争条件下工作
var e = document.createElement('div');
e.className = 'box e';
document.getElementById('wrapper').appendChild(e);
window.getComputedStyle(e).opacity; // added
e.className += ' in';
var $a = $('<div>')
    .addClass('box a')
    .appendTo('#wrapper');
$a.focus(); // focus Added
$a.addClass('in');
var e = document.createElement('div');
e.className = 'box e';
document.getElementById('wrapper').appendChild(e).focus(); // focus Added
e.className += ' in';
setTimeout(function () {
    requestAnimationFrame(function () {
        // trigger the animation
    });
}, 20);
el.style.display = 'block';
el.style.transition = 'opacity .5s linear';

// reflow
el.getBoundingClientRect();

// it transitions!
el.style.opacity = 1;
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";
  })
);