内容loading加载后高度变化CSS3 transition体验优化?
下面是张大神张鑫旭的文章.提出个问题.
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo</title>
<style type="text/css">
*{margin:0;padding:0;box-sizing:border-box;}
.box { width: 400px; padding: 20px; border: 40px solid #a0b3d6; background-color: #eee; overflow: hidden; }
.loading { height: 100%; background: url(ajax-loader.gif) no-repeat center; }
.in { width: 100px; margin: 0 auto; border: 50px solid #beceeb; background-color: #f0f3f9; }
[type=button] { width: 100px; height: 32px; font-size: 100%; }
</style>
</head>
<body>
<div id="box" class="box">...</div>
<p>
<input type="button" id="button" value="点击我">
</p>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script type="text/javascript">
var funTransitionHeight = function(element, time) { // time, 数值,可缺省
if (typeof window.getComputedStyle == "undefined") return;
var height = window.getComputedStyle(element).height;
element.style.height = "auto";
var targetHeight = window.getComputedStyle(element).height;
element.style.height = height;
setTimeout(function() {
if (time) element.style.transition = "height "+ time +"ms";
element.style.height = targetHeight;
}, 15);
};
(function() {
// demo演示脚本
var box = document.getElementById("box"), button = document.getElementById("button");
button.onclick = function() {
// 载入菊花,模拟loading效果
box.innerHTML = '<div class="loading"></div>';
// 随机高度内容
setTimeout(function() {
box.innerHTML = '<div class="in" style="height:'+ Math.round(400 * Math.random()) +'px;"></div>';
funTransitionHeight(box, 250);
}, 1000);
};
// 初始高度
funTransitionHeight(box);
})();
</script>
</body>
</html>
代码中这一段。
setTimeout(function() {
if (time) element.style.transition = "height "+ time +"ms";
element.style.height = targetHeight;
}, 15);
为什么要setimeout. 去掉就没效果了.. 张大神解释说是需要
触发动画效果需要触发重绘,setTimeout就有这个作用
小弟依然没太明白. 求解释......
松山爱妹妹
9 years, 6 months ago
Answers
一方面,CSS样式修改是渲染中的一种高成本操作,所以浏览器一般会缓存渲染树的更新。但有的情况则不会缓存,比如:
-
调整窗口大小和修改页面默认字体
-
client/offset/scroll(比如访问
node.clientWidth
属性) -
getComputedStyle()
currentStyle
另一方面,setTimeout 是要等执行线程空闲的时候才会触发的。
以上是原理。下面看问题:
假设没有
setTimeout
,效果成了:
// 立即重排
var height = window.getComputedStyle(element).height;
// 缓存之
element.style.height = "auto";
// 立即重排
var targetHeight = window.getComputedStyle(element).height;
// 下面开始重点:
// 缓存之
element.style.height = height;
// 缓存之
if (time) element.style.transition = "height "+ time +"ms";
// 缓存之
element.style.height = targetHeight;
// 渲染
结果就是,根本不会渲染高度为
height
,而是直接渲染成
targetHeight
。我们想要的结果是从
height
到
targetHeight
的过渡。
那有了
setTimeout
,效果就是酱紫的了:
// 缓存之
element.style.height = height;
// 空闲了才干
setTimeout(function() {
if (time) element.style.transition = "height "+ time +"ms";
element.style.height = targetHeight;
}, 15);
// 立即重排
喏喏,浏览器得先重排高度为
height
才闲下来,而一闲下来才要求重排到
targetHeight
,这才会产生过渡效果。
ransoma
answered 9 years, 6 months ago