立方体

立方体

上一节翻转卡片的例子对于学习3D变换来讲是一个不错的开始,但是这仅仅展示了过渡中的3D效果,为了展示静态的3D效果,我们需要做一个真实的3D物体:棱镜。下面我们从一个立方体开始。

立方体的HTML与卡片的十分相似,这次我们需要6个子元素对应立方体的6个平面。

<div class="scene">
  <div class="cube">
    <div class="cube__face cube__face--front">front</div>
    <div class="cube__face cube__face--back">back</div>
    <div class="cube__face cube__face--right">right</div>
    <div class="cube__face cube__face--left">left</div>
    <div class="cube__face cube__face--top">top</div>
    <div class="cube__face cube__face--bottom">bottom</div>
  </div>
</div>

下面是一些基础的位置和大小样式,将容器中的6个平面定位到彼此的上方。

.scene {
  width: 200px;
  height: 200px;
  perspective: 600px;
}

.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
}

.cube__face {
  position: absolute;
  width: 200px;
  height: 200px;
}

现在所有的平面都被置于另一个平面的上方,马上就可以进行旋转了。注意.cube__face--left.cube__face--right要使用rotateX()绕垂直的X轴进行旋转。

.cube__face--front  { transform: rotateY(  0deg); }
.cube__face--right  { transform: rotateY( 90deg); }
.cube__face--back   { transform: rotateY(180deg); }
.cube__face--left   { transform: rotateY(-90deg); }
.cube__face--top    { transform: rotateX( 90deg); }
.cube__face--bottom { transform: rotateX(-90deg); }

(我们可以移除rotateY( 0deg)这个样式,因为这个变换不会带来任何效果,但是让我们为了一致性还是把它保留)

现在所有的平面都旋转过了,但只有正面和背面是可以看到的。由于其它4个面与观察者是垂直的,只露出了边缘,所以近乎不可见。为了将平面放置到合适的位置,它们需要从它们现在交叉的中心向外平移。由于正方体的每一个边都是200px宽,所以它们需要相对立方体中心向外平移一半的距离,即100px。

.cube__face--front  { transform: rotateY(  0deg) translateZ(100px); }
.cube__face--right  { transform: rotateY( 90deg) translateZ(100px); }
.cube__face--back   { transform: rotateY(180deg) translateZ(100px); }
.cube__face--left   { transform: rotateY(-90deg) translateZ(100px); }
.cube__face--top    { transform: rotateX( 90deg) translateZ(100px); }
.cube__face--bottom { transform: rotateX(-90deg) translateZ(100px); }

这里注意translate函数是在ratate之后的,变换函数的顺序极其重要。每一个面首先旋转至正确的方向,然后再向远离中心的的方向平移。

至此,我们已经渲染出了一个立方体,但是还没有结束。

锐化3D变换后的文字

现在再看一下上边立方体里的文字,其实会有一些模糊。

3D变换会影响到文字渲染。当你应用3D变换时,浏览器先是拍下当前元素的快照,然后在3D变换开始后重新渲染它们的像素。因此3D变换后,文字原先的抗锯齿程度与变换后的大小不相匹配。

对于用户来讲,3D变换不应该扭曲变化用户界面。为了解决扭曲和字体模糊的问题,我们可以将这个3D物体向后平移,这样最前边的平面便被定位到了Z轴原点的位置上了。

.cube { transform: translateZ(-100px); }

旋转立方体

为了可以露出立方体的每一个面,我们需要添加一些样式,通过旋转立方体以露出对应的平面。我们在.cube上通过切换样式类来做合适的变换,而这些变换是与对应平面的变换方向相反的。

.cube.show-front  { transform: translateZ(-100px) rotateY(   0deg); }
.cube.show-right  { transform: translateZ(-100px) rotateY( -90deg); }
.cube.show-back   { transform: translateZ(-100px) rotateY(-180deg); }
.cube.show-left   { transform: translateZ(-100px) rotateY(  90deg); }
.cube.show-top    { transform: translateZ(-100px) rotateX( -90deg); }
.cube.show-bottom { transform: translateZ(-100px) rotateX(  90deg); }

注意变换函数的顺序是与之前相反的。首先我们用translateZ将立方体向后平移,然后再旋转。

最后我们在旋转状态之间加一个过渡效果。

.cube { transition: transform 1s; }

最后更新于