当下CSS3应用已经相当广泛,其中重要成员之一就是CSS3动画。并且,随着CSS动画的逐渐深入与普及,更复杂与细腻的动画场景也如雨后春笋般破土而出。例如上个月做的「企业QQ-新年祝福」活动: 感谢shirley帮忙录制上面的视频,虽然视频内容是手机上的显示效果,但是,这个“企业新年祝福活动”原本只针对桌面端,移动端是后来辅助增强(增加了相当于活动页面UV 5.7%的点击)。而目前大多数类似页面只针对移动端,例如其他同事实现的QQ空间5.0预约页第二版: 因此,需要多一点适配的技巧。但是,对于动画效果实现,其实都是一脉相承的,最终的实现需要很多点滴积累,我这里讲三个部分同学可能不知道的相关CSS技巧。 注:示例代码的私有前缀均省略,大家自行脑补 技巧一、使用animation-play-state控制每屏动画播放1. 类名active与动画触发 一般做法是,当对应一屏内容进入的时候,使用JS给容器添加类名 container.classList.add("active"); 如果你做的动画逼格较高,希望每次浏览这一屏内容的时候,动画都走一遍,可以使用reflow重新触发一下 container.classList.remove("active"); container.offsetWidth = container.offsetWidth; container.classList.add("active"); 2. 类名active与动画控制技巧 .element1 { /* 尺寸与定位 */ } .element2 { /* 尺寸与定位 */ } .element3 { /* 尺寸与定位 */ } ... .active .element1 { animate: name1 1s; } .active .element2 { animate: name2 1s; } .active .element3 { animate: name2 1s; } ... 从实现和功能上将,上面方法是很不错的,通俗易懂,不易犯错。不过我个人更喜欢使用配合CSS3的
之所以个人更喜欢后面的方法,是因为有一种“无侵入”的感觉,代码层次清晰,控制关系明确。有利于后期的维护与扩展。 然而,使用
只会让整个CSS声明挂掉的!如下写法支持: .element { animate: shake 4s 2s both infinite; animation-play-state: paused; } 有人可能要奇怪了,怎么突然IE浏览器乱入了? 首先,我们不能无视主流手机之Windows Phone. 其次,帅气的翻屏动画并不是移动端专有,桌面端也适用。稍稍用力,桌面移动全适配,何乐而不为! 技巧二、不同状态下的连续动画有时候,动画可能不是一波流,分状态。 例如,我们的小火箭,先是淡出动画,然后无限上下悬浮。怎么实现呢? 关键点就是动画分解与延时。 据我所知,没办法只使用一个 怎么办?我们可以将动画分解,写2个 @keyframes fadeIn { /* ... */ } @keyframes float { /* ... */ } 然后,再分别应用这些关键帧动画。如何应用呢?有2个小技巧: 1. 逗号与多animation动画值 <div class="element">小火箭</div>
.element { animation: fadeIn 1s, float .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒后开始无限漂浮 */
其中 此写法没有兼容性问题,大家可以开开心心地使用。 2. 标签嵌套与独立动画 <div class="element-wrap"><div class="element">小火箭</div></div> .element-wrap { animation: fadeIn 1s; } /* 我淡出, 需要1秒 */ .element { animation: float .5s 1s infinite; } /* 我1秒后开始无限漂浮 */ 有人可能会奇怪了。 ① 提取公用动画 如果纯粹借助 .element1 { animation: fadeIn 1s, float .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒后开始无限漂浮 */ .element2 { animation: fadeIn 1s, size .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒后开始大小变化 */ .element3 { animation: fadeIn 1s, move .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒后开始左右移动 */ 可以看到,淡出是公用的动画效果,我们可以借助嵌套标签,实现公用语法的合并,方面后期维护: .element-wrap { animation: fadeIn 1s; } /* 大家都1秒淡出 */ .element1 { animation: float .5s 1s infinite; } /* 我1秒后无限漂浮 */ .element2 { animation: size .5s 1s infinite; } /* 我1秒后忽大忽小 */ .element3 { animation: move .5s 1s infinite; } /* 我1秒后左右移动 */ ②避免变换冲突 @keyframes spin { /* transform: rotate... */ } @keyframes zoomIn { /* transform: scale... */ } 好了,现在问题来了,变放大边旋转: .element { animation: spin 1s, zoomIn 1s; } /* 旋转:啊,完蛋啦,我被放大覆盖啦! */
由于都是使用transform, 发生了残忍的覆盖。当然,有好事的人会说,你使用 怎么办?重新建一个名为 对啊,你直接外面套一层标签不就万事大吉了 : .element-wrap { animation: spin 1s; } /* 我转转转 */ .element { animation: zoomIn 1s; } /* 我大大大 */ 技巧三、无侵入定位和居中定位准则1. 这里的“无侵入定位”指不受 ①. 不使用 ②. 不使用 @keyframes spin { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); } } 要么使用业界约定俗成 @keyframes spin-trans { 0% { transform: rotate(0) translate(-50%,-50%); } 100% { transform: rotate(360deg) translate(-50%,-50%); } } 显然,都是不合适的。建议使用传统 2. 这里的“居中定位准则”包含两部分:一是元素定位在容器中间位置;二是元素的定位方式为居中定位。 ①. 元素定位在容器中间 举个简单例子,本文一开始展示的「企业QQ-新年祝福」活动。 企业产品用户特点比较鲜明:一是访问主要集中在桌面端,二是有70~80%用户使用的是webkit/blink内核浏览器。所以,大家可以理解为何设计稿明明针对桌面端,却有如此多细腻的动画设计了。 故事是这样的,桌面版做好了,1024-1224自适应,IE7以上都兼容(无侵入定位准则)(除了没动画),好棒!此时负责视觉的晓玲同学希望也能适配移动端,可以增加一定的传播,我觉得挺好的,于是,决定通过技术手段,让活动页面能游走于桌面和移动之间,同时,保证各种动画效果棒棒哒! 结果,发现自己留了一个坑,拿第2屏举例,桌面版,长这样,右侧动画内容并不是完全居中的: 本着高度还原设计稿的原则,所有动画元素都经过测量定位,按照PSD中的参考线左上角(left/top),结果整体左侧冒出60像素: 于是,问题来了,当移动端做响应式适配时候,由于容器内的动画元素不是居中的,所以—— 后来,进行了修改,内部动画元素整体居中,外部容器桌面端做左侧60像素偏移,于是,适配移动端时候,就正好是居中的啦。 ②. 定位方式为居中定位 我们在实现多元素动画效果时候,会出现两类角色:一是容器;二是容器里面诸多动画元素。 其中,对于容器元素,尤其在做移动端产品时候,我们很自然会让其居中定位: .container { position: absolute; left: 50%; top: 50%; transform: translate3d(-50%, -50%, 0); } 这样,各种尺寸的手机,我们都能让其居中显示(大尺寸可能需要一定的缩放)。 但是,我们有没有想过让容器里面的诸多动画元素也居中定位显示呢? 用代码来解释就是从左上角定位(或右上角定位): .example { position: absolute; left: 100px; top: 100px; } 变成中心点定位+ .example { position: absolute; left: 50%; top: 50%; margin-left: -100px; margin-top: -100px; } 有同学可能要疑问了,why? 前面一步到位不挺好的,后面这样分两步走岂不是多余? 在大多数情况下,我们的应用场景比较单一,或只需要玩转移动端,或只需要驾驭桌面端,此时,上面两种定位的优劣是看不出来的。 但是,遇到一些复杂的应用场景,尤其涉及到容器尺寸或定位方式改变的时候,后面的定位优势就可以看出来。 比方说一开始提到的qzone5.0的例子,如果我们把容器宽度加大(实际是不会的,示意目的),如 会发现,宇航员和飞船在小行星之外了,也就是动画元素不是聚拢状态了。 所以,大家看出居中定位的优势来了没有:
还是拿去年年底做的「企业QQ-新年祝福」活动举例,第8屏: 其中,中间的“王强”和“马老板”这些数据有可能是没有的,也就是很有可能这一屏只有文字和宇航员,但同时还要保持整体垂直居中。很显然,宇航员和火箭所在的容器不能是绝对定位,否则脱离文档流,不能和上面元素保持合适垂直间距同时垂直居中。我们仍然有2种实现方法:
方法1问题在于:
而方法2,屏幕尺寸再小,也是居中的,只不过两侧有所剪裁。最终,移动端适配时候,我们不必关心定位问题,只要合适缩放就可以了 : 结语首先,大家要明白,本文所展示的三个技术技巧属于个人经验建议,注意,是建议。里面所提到的所有解决方法都有更加直观、通俗的实现,对于大多数的产品而言,技术的价值体现已经足够;同时应用场景千千万,没有什么一方通行的方法,例如居中定位准则,有时候,可能就是需要非居中定位。 但是,作为一个有技术追求的技术从业人员,对技术的精益求精一定是有价值的,无论是对自己,还是公司。有人可能会反驳,我们这个项目明明只会针对移动端,你还花心思考虑低配的事情,岂不是白白浪费时间和人力成本。古人有云:“不以善小而不为”,这种去粗取精的小经验虽然看上去没什么实质性成长,对眼前项目也没多少价值体现,但是积累足够多,会产生质变的,填坑的事情少了,工作也更轻松与快乐,对公司产生的价值也更大。 高瞻远瞩积跬步,登峰造极至千里。 好了,以上就是自己对于多屏CSS动画方面的一些技巧体会,希望可以对大家的学习有所帮助。当然,资历有限,要是文中有什么表述不准确的地方,欢迎指正;也欢迎针锋相对的讨论,共同成长。 感谢你的阅读,本文由 腾讯ISUX 版权所有,转载时请注明出处,违者必究,谢谢你的合作。 |
|