当前位置: 首页 > Web前端 > HTML5

玩玩CSS3D-正八面体和正十二面体

时间:2023-04-05 21:10:51 HTML5

正八面体和正十二面体,虽然这两个正多面体组合面比较多,但是因为对称性,只需要做一半的结构,另一半就可以了以相反的方式连接在一起。正八面体正八面体可以想象成“两个金字塔”叠加在一起。为了方便我们后续旋转整个金字塔的动作,我们需要用另一个容器来包装金字塔。可以想象为改变金字塔的四个面。组成一个组,可以变换或移动组,HTML结构如下,空格中有box1和box2,box1是金字塔的上半部分,box2是金字塔的下半部分:

接下来先设置相机和空间。.camera{宽度:200px;高度:200px;-webkit-perspective-origin:50%50%;-webkit-perspective:500px;}.space{position:relative;宽度:100%;高度:100%;1px虚线#000;-webkit-transform-style:preserve-3d;}然后因为我们用的面都是三角形,所以还需要用border来实现。记住position要设置成absolute,而且因为box1,box2本身内部也是三维空间,所以transform-style的属性:preserve-3d也必须加上。.spacediv{position:absolute;}.box1,.box2{transform-style:preserve-3d;}.box1div,.box2div{width:0;高度:0;边框宽度:050px87px;边框样式:纯色;opacity:.4;}让我们再次制作box1的金字塔形状。由于正八面体每个面之间的夹角是109.28度,又因为它被分成两半,与中间相差54.64度,所以我们要旋转的角度是:90-54.64=35.36,所以后面我们要旋转的角度就以此为准,先看face1,沿x轴向内旋转35.36度。.face1{边框颜色:透明透明#f00;变换原点:中心底部;transform:translateX(50px)translateY(50px)rotateX(35.36deg);}face2首先要以右边为中心绕Y轴旋转90度,再绕X轴旋转35.36度。.face2{边框颜色:透明透明#00f;变换原点:右下角;transform:translateX(50px)translateY(50px)rotateY(-90deg)rotateX(-35.36deg);}face3和face1相对,所以先在Z轴上移动100px,然后绕X轴旋转35.36度。.face3{边框颜色:透明透明#0f0;变换原点:左下角;transform:translateX(50px)translateY(50px)translateZ(-100px)rotateX(-35.36deg);}face4和face2一样,只是face4左边是圆心。.face4{边框颜色:透明透明#f90;变换原点:左下角;transform:translateX(50px)translateY(50px)rotateY(90deg)rotateX(-35.36deg);}基本上这一边已经完成了上部box1的金字塔形状,此时box1和box2重叠,我们只需要将box2反转,改变位置,可以变成正八面体形状,但是这里我们会遇到一个很有意思的问题,box2变形的中心点在哪里?这时候就需要用到几个三角函数的计算,因为它是金字塔形状的旋转中心点,所以必须考虑Z轴。首先,设置X轴居中是没有问题的,Z轴是因为金字塔底部是一个100×100的正方形,所以中心点在50px是正常的,但是Y轴是比较麻烦。首先,我们看到等边三角形的一条边的长度是100px,中心线的长度是sin(60)x100=86.6左右,然后用sin(54.64)x86.6得到金字塔70.6,四舍五入得到71,所以当我们在这里设置变形中心时,会围绕金字塔顶部旋转,旋转180度后,需要使用translateY回到位置,移动的距离大概是100+71/2=135,但是因为我们一开始就用了四舍五入,所以最后用整数难免会出现性能上的误差(两个金字塔是连不上的),然后手动微调是必须的,这里设置为-132px。.box2{transform-origin:center71px-50px;transform:rotateX(180deg)translateY(-132px);}同样的,旋转空间使得整个正八面体旋转,看起来更加立体。.space{位置:相对;宽度:100%;高度:100%;-webkit-transform-style:preserve-3d;-webkit-transform-origin:centercenter-50px;-webkit-animation:s4s线性无限;}@-webkit-keyframes{0%{-webkit-transform:rotateY(0);}100%{-webkit-transform:rotateY(-359.9deg);十二面体的原理几乎是一样的,但是正十二面体比较复杂,因为它是由十二个正五边形组成的,只不过这里是从正五边形的五个边长出五个面,每个面之间的夹角是116.56度,180-116.56=63.44,以后用的角度大概不会偏离这两个值,当然因为小数点很多,还是要手动微调(因为像素的最小单位是1)。HTML的结构如下,同样分为两部分,每部分有六个面。先设置一个开始的CSS。.camera{宽度:200px;高度:200px;透视原点:50%0%;-moz-perspective-origin:50%0%;-webkit-perspective-origin:50%0%;视角:500px;-透视:500px;-webkit-perspective:500px;}.space{position:relative;宽度:100%;高度:100%;边框:1px虚线#000;变换样式:保留3d;样式:保留3d;-webkit-transform-style:preserve-3d;}.spacediv{position:absolute;}.box1,.box2{transform-style:preserve-3d;-moz-transform-style:preserve-3d;-webkit-transform-style:preserve-3d;}接下来,慢慢画出每张脸。首先,画出所有的正五边形。.box1div,.box2div{宽度:162px;高度:154px;opacity:.9;}.box1div:before,.box2div:before{position:absolute;内容:””;顶部:0;宽度:0;高度:0;边框宽度:081px59px;边框样式:实心;border-color:transparenttransparent#069;}.box1div:after,.box2div:after{position:absolute;内容:””;顶部:59px;左:0;宽度:100px;高度:0;背景:无;边框宽度:95px31px0;边框样式:实心;多边形的五个边向外长出五个面,所以face1不会改变,然后可以旋转盒子。对于face2到face6这五个面,比较简单的方法是先直接旋转Z轴。动作,然后进行Y轴旋转,然后将各个面平移到对应的位置,但是这里一定要非常小心,因为我们先进行了Z轴和Y轴旋转,所以每个面的坐标系都有改变了,可以参考下图,就可以明白怎么平移了,基本上是在Y轴旋转-116.56度后,每个面先向自己的Y轴移动69px,然后为了让所有的边都对齐,它必须向Y轴移动31px(cos(180-116.56)x69),向Z轴移动62px(sin(180-116.56)x69)。所以face2到face6几乎可以这样写(Z轴旋转角度各为72度)。face2{transform-origin:81px85px0;transform:rotateZ(0)rotateX(-116.56deg)translateY(-69px)translateY(-31px)translateZ(62px);}.face3{transform-origin:81px85px0;transform:rotateZ(72deg)rotateX(-116.56deg)translateY(-69px)translateY(-31px)translateZ(62px);}.face3{transform-origin:81px85px0;变换:rotateZ(72deg)rotateX(-116.56deg)translateY(-69px)translateY(-31px)translateZ(62px);}.face4{transform-origin:81px85px0;变换:rotateZ(144deg)rotateX(-116.56deg)translateY(-69px)translateY(-31px)translateZ(62px);}.face5{transform-origin:81px85px0;变换:rotateZ(-144deg)rotateX(-116.56deg)translateY(-69px)translateY(-31px)translateZ(62px);}.face6{transform-origin:81px85px0;transform:rotateZ(-72deg)rotateX(-116.56deg)translateY(-69px)translateY(-31px)translateZ(62px);}为了让每个面都有不同的颜色,这里必须改变伪元素的边框颜色.box1.face2:before{border-color:transparenttransparent#f00;}.box1.face2:after{border-color:#f00transparenttransparent;}.box1.face3:before{border-color:transparenttransparent#0f0;}.box1.face3:after{border-color:#0f0transparenttransparent;}.box1.face4:before{border-color:transparenttransparent#f90;}.box1.face4:after{border-color:#f90transparent透明;}.box1.face5:before{border-color:transparenttransparent#09f;}.box1.face5:after{border-color:#09ftransparenttransparent;}.box1.face6:before{border-color:transparenttransparent#f0f;}.box1.face6:after{border-color:#f0ftransparenttransparent;}最后旋转box1和box2。这里需要注意的是translateZ。整个正五边形的高度是276(sin(63.44)x154x2),但是位移不正好是这个高度,必须减去关节短边的高度,所以会变成223(276-sin(36)x100).box1{transform-origin:81px85px0;transform:rotateX(90deg)translateZ(-223px);}.box2{transform-origin:81px85px0;transform:rotateX(-90deg);}space加动画效果,验证每个surface是否有连接的完美.space{position:relative;宽度:100%;高度:100%;-webkit-transform-style:preserve-3d;-webkit-transform-origin:81px170px0;-webkit-animation:s4s线性无限;}@-webkit-keyframess{0%{-webkit-transform:rotateY(0)rotateX(0);}100%{-webkit-transform:rotateY(-359.9deg)rotateX(359.9deg);}}