从下半年开始,我尝试在活动页面中添加css3动画,让标准浏览器的用户能够看到更加炫的效果。一直小打小闹的试验着各种效果~前不久,鬼哥跟我说有个活动要大量使用css3动画,各种动!内心一阵狂喜~~
这是与南航公司合作的活动,用户通过选择航线(欧洲线或北美线),每个航线4个城市,完成航线后转发微博即可参与抽奖。城市间通过css3动画转场切换,对于IE浏览器通过JS做切换。每个城市还会使用css3让小元素动起来。
经过三周的努力,活动终于上线了,但是过程并非想象那么顺利。
过程中遇到的问题下面跟大家分享一下:
分享内容:
- 活动HTML剖析
- 动画实现
- 遇到的问题及解决方法
- 按需加载
- 图片裁剪
- 图片文字
- 自适应
- fixed定位问题
- 经验总结
【活动HTML剖析】
由于航程的8个城市需要随着地球转动进行切换,8个城市的内容需要对底部的地球相对定位,这样控制地球转动就能实现城市转场。
【动画实现】
1.地球是由CSS3绘制出来的一个大圆,把各个城市的图片定位在大圆上面,滚动大圆达到切换城市转场的效果。
03 | position:fixed;z-index:19; |
04 | left:50%;top:81%;margin-left:-1113px; |
05 | width:2226px;height:2226px;border-radius:2226px; |
09 | @-webkit-keyframes ball{ |
10 | 0%{opacity:0.8;-webkit-transform:rotate(0deg);} |
11 | 50%{opacity:0;-webkit-transform:rotate(-45deg);} |
12 | 100%{-webkit-transform:rotate(-90deg);opacity:1;} |
2. 城市内的元素漂浮
都是使用的以下这个动画,对元素位移的变化以及旋转。只是播放时间的长短不同~这样可以简化代码的同时又能实现需要的效果。
1 | @-webkit-keyframes swing{ |
2 | 20%, 40%, 60%, 80%, 100% { -webkit-transform-origin:bottom center; } |
3 | 20% { -webkit-transform:translate(3px,0) rotate(25deg); } |
4 | 40% { -webkit-transform:translate(5px,2px) rotate(-20deg); } |
5 | 60% { -webkit-transform:translate(-1px,-11px) rotate(15deg); } |
6 | 80% { -webkit-transform:translate(-11px,-1px) rotate(-15deg); } |
7 | 100% { -webkit-transform:translate(0,0) rotate(0deg); } |
【遇到问题以及解决】
1. 按需加载
【过程尝试】
最初前端同学以为是使用主站那种img标签不进入屏幕的图片就不进行加载。
沟通后,前端同学提出把图片加在HTML,由ID控制载入,如下图结构:
但是很快认识到,图片最先已经在样式中加载了,JS无法控制。前端同学提出样式按需加载。
需要重构把大样式分离成以下部分,由JS动态加载。
但是JS只能用Link的形式把样式插入页面,不方便重构更新样式时间戳。
【目前方案】
经沟通,Wynn提出了更好的方法:
把样式名写在节点的自定义属性,需要加载时使用JS给节点的class属性赋上自定义熟悉的值,此时,客户端才会请求相应的图片。
这个方案的优点:
- 保持样式完整,方便更改时间戳以及后期维护。
- 请求缩减为一个,比之前分成7个样式相应需要发送7个请求节省了发送时间和等待时间(1ms+4ms)*(7-1)=30ms,而实际上,拆分后的样式字节数请求会比整个样式大,节省的时间是>30ms的。
2. 图片裁剪
活动的图片太多,除了通过按需加载控制,还要在裁剪的时候控制输出大小。以求最优。例如:飞机正着切是95.4k,而按设计稿斜着切是114.4k,相差19K。但是对于不支持旋转的IE需要使用滤镜,这个相对又减慢速度了。
那尝试对斜切的飞机进行无损压缩:
除了通过无损压缩还可以在裁切的时候,多注意细节。例如,当背景图大于100K,我会把它拆分成几个图片再合成,此时根据元素高度进行裁切就可以省下字节数。
3. 图片文字
每个城市的右侧文字视觉使用了手写体,所以都是使用的图片,这给维护带来麻烦。
至此更换了两次,每次更换8个城市需要一天,因为其中还包括链接按钮图片定位。
【过程尝试】
方案1,为了更好的替换,尝试在说明文字使用微软雅黑字体,但是设计师认为没有达到活动的设计效果,只有放弃了。
方案2,有童鞋提出了可以使用@font-face,我试验了一下,它的优点是适合SEO,特别适合用于英文字体。但对于中文字体,动辄几M,目前还没有工具可以实现把需要使用的特殊字体抽离;而且在网页上引用字体需要获取引用版权。鉴于此,使用@font-face的想法,在有限的时间内,只能放弃了。
附上@font-face的使用:
获取要使用字体的三种文件格式,确保能在主流浏览器中都能正常显示该字体。
.TTF或.OTF,适用于Firefox 3.5、Safari、Opera
.EOT,适用于Internet Explorer 4.0+
.SVG,适用于Chrome、AndRoid、IPhone
获取字体格式的网站有以下几个:
1. http://onlinefontconverter.com/
Online Font Converter是一个可以帮你把字体在eot otf pfb pfm suit svg ttf pfa bin pt3 ps t42 cff afm ttc woff等格式中互相转换的网站。
2. http://ttf2eot.sebastiankippe.com/
可以将ttf字体转换为eot字体,且最大支持10M的文件
3. http://www.fontsquirrel.com/fontface/generator
兼容格式较多(eot svg ttf woff),但目前只支持英文字母,不支持中文。
方案3,保留拼合文件的文字PSD,后续有修改邀请视觉直接修改拼合PSD。
【目前方案】
最后使用了方案3,希望以后能有更好的方案。
3. 自适应
活动的主要元素都使用了绝对定位,脱离了文本流,所以只能识别body内的高度,那如何做到自适应成了个问题。
【过程尝试】
地球的圆的直径是2226px,多余的部分是对body使用了overflow:hidden;
但是这个设置会导致窗口缩小后无法出现滚动条,如果要出现滚动条就会把下方要隐藏的球暴露出来~~
方案1,对每个城市里面的内容加个固定高度的容器,那就能把多余的地球部分隐去,但是这样做需要对每个城市里的元素都重新定位,因为每个城市高度不一样,还需要统一高度,不够便利,否决。
方案2,使用一个木有元素但属于文档流中的div,包裹住地球。针对该活动把div的最小宽高分别设为755px,1250px。即使div内没有元素,但是当窗口小于这个值就会触发body产生滚动条。
1 | .container{position:relative;height:100%;width:100%;margin:0 auto;min-height:755x;min-width:1250px;overflow:hidden;} |
但是,由于页面内的内容都不在正常文档流中,在chrome等标准浏览器就只能识别到容器的最小高度为755px,无法使城市的CSS3渐变背景随着高度自适应。尝试了padding:9999px;margin:-9999px的方法也没有作用。尝试通过JS给body动态更新min-height的值,但是前端同学没有实现。
【目前方案】
最后使用了方案2实现自适应的问题,渐变的实现只有舍弃了,希望以后有更好的解决方法。
4. fixed定位问题
由于界面元素太多。当窗口变窄的话,元素会重叠在一起。
主要原因是下面的圆使用了fixed,定位在页面最下方。
解决办法就是当页面高度小于临界值的时候,把地球的定位改为绝对定位,使得上面元素不被遮住。这个在chrome等标准浏览器可以通过下面媒体查询的方法实现:
1 | @media only screen and (max-height:755px){ |
2 | .container{position:relative;height:100%;width:100%;margin:0 auto;min-height:755px;min-width:1024px;overflow:hidden;} |
3 | .ball{top:550px;position:absolute;} |
6 | @media only screen and (min-height:755px){ |
7 | .container{position:relative;height:100%;width:100%;margin:0 auto;overflow:hidden;} |
对于IE类浏览器只有通过JS判断可视区域的高度,对body节点增加.min-heigh的样式,对该样式下的元素进行自定义。
1 | .container{position:relative;height:100%;width:100%;margin:0 auto;min-height:755px;min-width:1250px;overflow:hidden;} |
3 | .min-height .container{position:relative;height:100%;width:100%;margin:0 auto;min-height:755px;min-width:1250px;overflow:hidden;} |
5 | .min-height .ball{top:550px;position:absolute;} |
【经验总结】
- 使用动画可以做在大动作上,小元素可以使用gif替代,提高性能。
- 预知修改,拼合图保存好完整的PSD。
- 管理好自己的本地开发文件,不与JS文件混用,避免JS影响页面效果,也可以方便别人调试查看,还可以带回家做。
- 遇到难题多和同事沟通,思路会清晰明了。柳暗花明又一村。非常感谢鬼哥,fish,wynn,德生,佳佳,jojo等童鞋给予的建议与帮助。
来源:腾讯TID