记一次CSS弹出动画的Bug
2016-03-29 16:13
435 查看
在写 jQuery WeUI 的一个picker的弹出动画的时候,我是通过CSS动画实现的。
CSS代码如下:
JS代码如下:
其实原理很简单,就是创建DOM的时候,通过 translate 把弹窗Y轴向下平移 100%,于是就看不到了,然后显示的时候再设置 Y 轴平移为0,就可以看到一个CSS动画的弹出效果。
但是测试发现在 iOS版的微信中就无法出现弹出动画,安卓以及PC上都没问题。
按道理讲是应该有动画的,因为我是先创建了DOM,并插入到页面,然后才添加了
注意这一行奇怪的代码
本来是先把DOM插入文档流,然后进行DOM操作,优化后大致相当于变成了这样:
那么很明显,这样做是无法出现动画的。而如何避免出现这种情况呢,之前的博客也提到了,就是在插入文档流之后,执行一次读取CSS属性操作,于是浏览器不得不立刻执行插入操作才能计算出CSS的属性值:
只需要改动一行代码即可解决这个bug。之前认为进行一次
可能有人要问为什么只有iOS上有这个问题,那估计是因为iOS更加重视这种UI上的性能优化,所以尽量进行DOM操作的合并。
所以如果大家以后自己写CSS动画,创建一个DOM之后立刻加一个类进行动画,也有可能会碰到这种bug,那么只需要在添加动画类之前随意读取一个CSS属性即可。
CSS代码如下:
.weui-picker-modal { width: 100%; position: absolute; z-index: 100; bottom: 0; text-align: center; border-radius: 0; opacity: 0.6; color: @color-text; transition-duration: .3s; height: 13rem; background: #EFEFF4; transform: translate3d(0, 100%, 0); transition-property: transform, opacity; &.weui-picker-modal-visible { opacity: 1; transform: translate3d(0,0,0); } }
JS代码如下:
$.openPicker = function(tpl) { var container = $("<div class='weui-picker-container'></div>").appendTo(document.body); container.show(); container.addClass("weui-picker-container-visible"); //关于布局的问题,如果直接放在body上,则做动画的时候会撑开body高度而导致滚动条变化。 var dialog = $(tpl).appendTo(container); // dialog.show(); //注意这一行奇怪的代码 dialog.addClass("weui-picker-modal-visible"); return dialog; }
其实原理很简单,就是创建DOM的时候,通过 translate 把弹窗Y轴向下平移 100%,于是就看不到了,然后显示的时候再设置 Y 轴平移为0,就可以看到一个CSS动画的弹出效果。
但是测试发现在 iOS版的微信中就无法出现弹出动画,安卓以及PC上都没问题。
按道理讲是应该有动画的,因为我是先创建了DOM,并插入到页面,然后才添加了
weui-picker-modal-visible类做动画。但是事实却是iOS上第一次没有弹出动画,那么也就意味着其实在IOS上,创建DOM和添加
weui-picker-modal-visible其实是合并成了一步,才会出现打开的时候没有弹出动画。
注意这一行奇怪的代码
dialog.show(),其实这一行代码就是想确保在添加类之前让DOM已经创建完毕。然后突然想到之前我有研究过JS性能优化相关的内容,其中有一条大意就是“如果连续对DOM进行多次操作,浏览器可能会调整这些操作的顺序以提升性能”,其实就是说浏览器会把DOM的修改操作尽量提前到被插入文档流之前进行,因为插入文档流之前进行修改就不需要进行渲染,所以这里其实如下三行代码在IOS中其实被提前到了DOM插入操作前:
var dialog = $(tpl).appendTo(container); // dialog.show(); //注意这一行奇怪的代码 dialog.addClass("weui-picker-modal-visible");
本来是先把DOM插入文档流,然后进行DOM操作,优化后大致相当于变成了这样:
var dialog = $(tpl); dialog.show(); //注意这一行奇怪的代码 dialog.addClass("weui-picker-modal-visible"); dialog.appendTo(container); //把上述三行代码先执行,然后再插入文档流,以提升性能。
那么很明显,这样做是无法出现动画的。而如何避免出现这种情况呢,之前的博客也提到了,就是在插入文档流之后,执行一次读取CSS属性操作,于是浏览器不得不立刻执行插入操作才能计算出CSS的属性值:
$.openPicker = function(tpl) { var container = $("<div class='weui-picker-container'></div>").appendTo(document.body); container.show(); container.addClass("weui-picker-container-visible"); //关于布局的问题,如果直接放在body上,则做动画的时候会撑开body高度而导致滚动条变化。 var dialog = $(tpl).appendTo(container); dialog.width(); //改动这一行代码,通过取一次CSS值,强制浏览器不能把上下两行代码合并执行,因为合并之后会导致无法出现动画。 dialog.addClass("weui-picker-modal-visible"); return dialog; }
只需要改动一行代码即可解决这个bug。之前认为进行一次
show操作就可以保证已经实际插入文档流了,这种想法是错的,只有进行一次CSS属性的读取才能百分百保证。
可能有人要问为什么只有iOS上有这个问题,那估计是因为iOS更加重视这种UI上的性能优化,所以尽量进行DOM操作的合并。
所以如果大家以后自己写CSS动画,创建一个DOM之后立刻加一个类进行动画,也有可能会碰到这种bug,那么只需要在添加动画类之前随意读取一个CSS属性即可。
相关文章推荐
- CSS3可使用动画的属性
- JS性能优化
- css sprite 动画制作
- css动画
- 超棒的跨浏览器纯CSS动画实现 - Animate.css
- 纯CSS方式实现CSS动画的暂停与播放!
- VUE+WebPack游戏设计:用CSS实现扑克牌翻转特效
- CSS-DOM
- 共享 load事件--addLoadEvent
- css3动画-animation属性
- Creating Web Animations-OReilly 2017 读书笔记
- 纯CSS实现小车动画
- CSS动画详解
- CSS各种动画效果
- css动画属性实现3d效果立体盒子效果
- 前端案例--纯css动画transform视距3D旋转
- 前端模型--css动画(旋转八音盒)
- JS引入方式及性能
- CSS动画:
- CSS3新特性学习