今次就来个大家用3D属性最爱炫技的场景,旋转的立方体,有人声称这种动画简直代表了CSS3的癫疯,不不,是巅峰。做完之后只想吼一声,你说的没差!由平面动效进阶到立体动效真是……立方体六个面要做足足六种不同的设置,所以那些玩八面体,十二面体,……等等的,大写的“服”字。其他人做的立方体3D动画,看了几个,差不多都是<div>
实现的,嗯哼,我用<SVG>
来做一下吧,至于原因嘛,后面揭晓,当然,如果失败的话,此句请自动忽略。
1. 先立起来
不可避免的,要先来个基础图形。错错错,是基础物体,反正就是个需要立体的东西,随便怎么称呼。基本上有两种方法可以实现,先来一种直观好理解的。
看上面这张图,我把立方体的六个面平铺开,右上角的那个是后面。此时,假设立方体是在视线正前方,好了,面有了,现在需要把它们折叠起来,像折纸盒一样,组成一个立方体。先看一下dom结构。
<div class="stage">
<div class="content">
<svg id="cubic1" xmlns="http://www.w3.org/2000/svg" >
<rect height="200" width="200" />
</svg>
<svg id="cubic2" xmlns="http://www.w3.org/2000/svg" >
<rect height="200" width="200" />
</svg>
<svg id="cubic3" xmlns="http://www.w3.org/2000/svg" >
<rect height="200" width="200" />
</svg>
<svg id="cubic4" xmlns="http://www.w3.org/2000/svg" >
<rect height="200" width="200" />
</svg>
<svg id="cubic5" xmlns="http://www.w3.org/2000/svg" >
<rect height="200" width="200" />
</svg>
<svg id="cubic6" xmlns="http://www.w3.org/2000/svg" >
<rect height="200" width="200" />
</svg>
</div>
</div>
非常简单,我定义了两个容器,一个是舞台stage,一个是包裹立方体的content,content里是6个SVG,每个SVG只有一个简单的矩形rect。我的目的是让content在stage里进行3D动效变化。
CSS定义如下:
.stage {width: 800px; height: 600px; background:#e5fffb; perspective:1000px;}
.content{transform-style: preserve-3d}
#cubic1{fill:#f29a76}
#cubic2{fill:#61BFBE}
#cubic3{fill:#BADDD6}
#cubic4{fill:#FFB5BA}
#cubic5{fill:#866667}
#cubic6{fill:#E25D6E}
SVG {position: absolute;top:200px; left:300px;width:200px; height:300px}
6个SVG都是宽200,高200,虽然里面的矩形<rect>
也都是相同尺寸,却没有进行统一的定义,是因为想尝试后期给每个SVG定义不同的动画属性。容器的摆放关系如下图:
目前,通过position属性的设置,六个面是重叠在一起的,因此,在折叠之前,先把每个方块挪到自己对应的位置。移动的CSS属性就很简单了。根据图示,cubic1,也就是正对着我们的面,不需要移动,其他增加transform: translate相应的属性设置,定义如下:
#cubic2{fill:#61BFBE;transform: translateZ(-200px)} /*后面远离屏幕200px移动*/
#cubic3{fill:#BADDD6;transform: translateY(-200px)} /*上面垂直向上200px*/
#cubic4{fill:#FFB5BA;transform: translateX(200px)} /*右面水平向右200px*/
#cubic5{fill:#866667;transform: translateY(200px)} /*下面垂直向下200px*/
#cubic6{fill:#E25D6E;transform: translateX(-200px)} /*左面水平向左200px*/
移动之后的效果是下面这种(闲着也是闲着,我把移动过程做了动效):
好了,现在各在其位,下面要各司其职,进行折叠了。
这里有一点要说明,就是移动过之后,关于坐标系的变化,拿其中一个面cubic4为例来说,当发生水平向右移动200px后,此时坐标系也会发生变化同样的位移,因此在做折叠(旋转)90度的3D变形时,旋转的基轴虽然在原坐标系是右边的垂直轴,但对于移动后的坐标系,变成了左边的垂直轴,因此,对应的变形原点的设置为transform-origin: center left。举一反五,其他的几个就不一一细说了,直接放上增加3D旋转后的CSS3属性(cubic2仅仅发生了Z轴方向的位移,没有旋转动画,所以无需设置)。
#cubic3{fill:#BADDD6;transform: translateY(-200px) rotateX(90deg) ;transform-origin: bottom center;}
#cubic4{fill:#FFB5BA;transform: translateX(200px) rotateY(90deg);transform-origin: center left;}
#cubic5{fill:#866667;transform: translateY(200px) rotateX(-90deg);transform-origin:top center;}
#cubic6{fill:#E25D6E;transform: translateX(-200px) rotateY(-90deg);transform-origin: center right;}
完成之后,效果是下面这种:
(这特么是不是在逗我,就一个平面非说是个立方体……!)别急,就知道你会这样说,所以我用动效展示一下这个过程:
此处应有动画!!应有动画!!应有动画!!(我忘记录屏了,天雷滚滚)
这下信了吧?其实这货就是个立方体,货真价实,只不过我们没有给最外层的容器(也就是3D变形的舞台)设置透视点位置,默认是屏幕正前方,所以你只看到了一面。来来来,我把透明度调整一下,再改改透视原点的位置,效果是下面这种。哟,立方体出来了。
上面说过,关于立方体的组成有两个方法,我们第一种是用了先平移后折叠,那第二种就是先折叠后平移了。说到这里,可能会不解,无所谓了管它呢,有甚区别,我自己做的过程中感觉差别还蛮大,下面这种方法要求对空间的理解能力更强,但代码却优化了很多,省去一干transform-origion的设置。在上面的组合立方体的过程中,我们把面向自己的那一面作为了二维的基面,其他方形都是基于此进行了变换,也就是说最后组成的立方体从三维角度来说,是向背离屏幕的Z轴进行延伸的(代表背面的cubic2进行了Z轴负向的位移)。
这次,我们假定组成后的立方体的中心就是坐标系的原点,首先,我仍然是用绝对定位法把所有的组成面都固定到容器统一的位置,只进行位移的正面和背面不用管,先来进行3D方向的旋转。依旧用动画表示吧。这里为了能看到效果,我把舞台stage的透视原点定义为偏右下方perspective-origin:80% 80%。
动画效果有了,只是由于透视点的方向问题,结果似乎少了两个面,再把透视点改成偏左上perspective-origin:20% 20%看一下:
完成第一步的旋转,下面就是要进行全体位移了,那么重点来了。
以左面cubic6为例,如下图所示:
在进行3D旋转变形后,坐标系也相应的做了旋转变形,从视觉角度来看,做完选择变形后的cubic6要进行向左移动100px的水平位移,但由于坐标系变形的缘故,对于其本身旋转后的坐标系而言,此时水平方向变成了Z轴,因此水平位移也就变成了translateZ。 把第二种方法形成立方体的动画看一下:
方法二之所以更优化,是因为关于六个cubic的定义简化如下:
#cubic1{fill:#f29a76;transform:translateZ(100px);}
#cubic2{fill:#61BFBE;transform:translateZ(-100px);}
#cubic3{fill:#BADDD6;transform:rotateX(90deg) translateZ(-100px)}
#cubic4{fill:#FFB5BA;transform:rotateY(-90deg) translateZ(100px)}
#cubic5{fill:#866667;transform:rotateX(-90deg)translateZ(-100px)}
#cubic6{fill:#E25D6E;transform: rotateY(90deg) translateZ(100px)}
2. 再转起来
基础部件已经搭起来了,下面就让这个立方体动起来。说立方体不好理解,但我们在做的时候把它放到了一个content<div>
容器里,因此,让这个容器做一些变换就可以了。至于用哪种方法得到的立方体,此处随意,我用了二。先来个最简单的绕Y轴旋转的,CSS部分如下:
@keyframes content{
to{transform: rotateY(360deg)translateZ(20px)}
}
.content{transform-style: preserve-3d; animation:content 2s linear both infinite; }
效果:
写到这里暂时停一下,剩下的放到另一篇吧,我要好好想一下关于3D能做哪些炸裂的效果。等更新。