用LESS递归生成CSS KEYFRAMES代码实现自动轮播的幻灯片
之前项目中用 css animation 制作了一个自动轮播的幻灯片的效果,从开始的 2D版 到后来的 3D版 ,成果可喜,制作过程中也对 css 的 animation 属性、 transition 属性顺便有了比较全面的认识。
###动画原理
2D版效果中,每一张幻灯片分别展示,在翻转到与屏幕垂直时,下一张幻灯片进入画面。
在实现过程中,首先定义了一个 animation 动画,动画描述了在所有幻灯片完成一个播放周期中单张幻灯片在每一时刻所处的状态,这包括自身做展示期间的状态和展示结束后一直等待到下一次展示期间的状态,然后将动画过程应用到幻灯片上。
图示中,3.5s时的状态与0.5s时的状态相同,0到0.5s、3.5s到4s为执行动画的过程,对应进入、离开画面的动画效果。直到一个周期结束之前,都处于离开画面的状态,这段时间由其它幻灯片执行动画效果。从4s开始,第二张幻灯片开始进入画面。
虽然所有幻灯片做的动画效果相同,但它分是分开相对独立做动画的,为了使整个动画效果比较流畅,做动画效果时需要相互协同。由于动画过程包括了当前幻灯片展示期间的状态和展示结束后其的状态,因此可将各幻灯片执行动画的时机采用时间差来连贯起来,这使用了下面的属性:
animation-delay
查看源码会发现, delay 值都是负值,这么做的原因是为了让动画开始后,所有的幻灯片都进行动画状态,而不是等到需要展示的时候才开始动画。这样做也免去了设置各幻灯片默认值的麻烦。
另外,第一张幻灯片也有 delay 值,这只是为了调整动画执行的状态。由于定义的动画过程中,幻灯片最初是从与屏幕垂直的方向开始的,因此要让第一张幻灯片在动画开始时就展示完毕,提前了动画开始的时机。当然调整动画过程可以不必这样做,我这里是将错就错了(XD)
后来由于2D版效果稍显单薄,便调整为3D版。
3D版调整的主要部分,在幻灯片由原先的单个平面,转变成了一个多面体,有几张幻灯片,就组成一个几面体,实现围绕多面体的中心轴旋转实现3D效果。
实现3D版效果时,最初希望依照2D版的实现方法,对每一张幻灯片应用动画过程。因此调整的主要工作量,就在于把幻灯片在多面体中每一时刻的状态做成动画过程。在最初的制作过程中,由于空间相像能力有限,纠结不出整个过程的实现,最终转换了思维方式:先将所有幻灯片组装成多面体的静止状态,再为整个多面体添加动画过程,以实现动画效果。
整个实现过程严重参照了优秀的 天气WebApp 以及 张鑫旭的教程和实例 ,在此表示强烈感谢。
在实现过程中,为了落实学习成果,模仿制作了 手势操作的立方体动画 ,生成了简要的 原理演示页面 ,在做动画的过程中,通过 Debug 的方式能够清楚地查看到动画执行过程中,各幻灯片的状态:
在项目开发中,使用了 less 辅助 css 开发,实现3D版效果时涉及到的小计算过程,就使用了 less 的“高级”功能,动态计算了一下。当然这样做没啥实质用处,只不过给重复又无聊的 css 写作过程加了点新鲜玩法,还是有点意思的。
但是,虽然使用了 less 辅助 css 开发,但多的也只是简单地用了函数的方式避免兼容属性的繁杂写法,复杂的代码生成等高级功能却没能用到(不会用的因素较多一点),查看源码,发现写完的 css 代码并不多,也是按照规律写出来的,总想用生成的方式写一写,但最终没能成功。
难得的偶然,再一次冲动,竟成功了!
###用LESS递归生成代码
事情的起因,是偶然想到查看 Bootstrap 的网络系统生成代码:
.spanX (@index) when (@index > 0) {
(~".span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
这不是“递归”么?这种发现的惊喜,就像之前在几个数值之间发现“勾股定理”一样让人兴奋。照猫画虎,对照着之前写好的 keyframes css 代码,建立了用 less 生成 keyframes 的代码、初始化各幻灯片状态以组装多面体的静止状态的代码,最终通过优化、提取公共变量,将代码整理为可快速生成3D效果多幻灯片的 代码生成版本 ,可以 查看 less 源码 了解实现过程。
cube-animation 工具中核心代码包含两部分:生成 keyframes 的代码、生成 init 初始化静止状态的代码。.vertical 生成了垂直方向上轮播的代码。
代码不复杂,对照代码中的注释也比较容易理解代码的实现过程。在实现过程中,遇到不好解决的问题,最突出的是字符串(算式)的书写方式。代码中,很多计算过程都单独书写,并赋值给一个变量,这么写虽然方便阅读代码了,但实质是由于混合书写让结构难以维护,也很难书写正确,才写成了最终的样子。
综合看来,代码中值得提的有以下几点:
-
Math.floor(X * 100) / 100 是 js 代码,用来取小数点后两位。
-
由于在 less 中,属性名不能由字符串拼接,因此 .keyframe 调用的时候对前缀及名字的组合采用了手动的方式。不过仍然有人 用代码生成了keyframe ,膜拜大神,但这样的写法,代码结构上稍有弱化,难读,个人不推荐。
-
venderWebkit 等变量用于做比较,以确定 .keyframe 中 .transform 兼容函数输出代码的前缀。
###最后
项目开发中使用 less 有段时间了,对它的特性使用,也不改太过依赖,也难向团队中推广,目前只是当作一种代码管理的辅助工具主要使用。
这次对代码生成的开发方式实践,虽然生成的代码没有多少实际用途,生成方式也可以用js实现,但这对开拓思路还是有积极意义的。 css 不只是简单的属性组合,在一些特效动画中,往往有数似“勾股定理”一样的数学关系存在,把它们整理清楚了,相信再写类似的代码时,生成过程就不是难事了。
blog comments powered by Disqus