前面两个课程中我们分别制作了3D立方体和3D长方体,掌握了它们的制作方法说明你已经会使用CSS3 3D transforms了。下面我们接着来谈谈更为高级的内容-3D旋转木马。当谈到3D旋转木马,开发者可以有许多种方式来实现它,但既然浏览器有实现3D空间的能力,我们为何不试一试使用CSS来实现一个旋转的3D旋转木马效果呢?
3D旋转木马的HTML结构和立方体、长方体和卡片的HTML结构基本类似,只是面多了一些。我们这里使用9个面来制作旋转木马:
<section class="container"> <div id="carousel"> <figure>1</figure> <figure>2</figure> <figure>3</figure> <figure>4</figure> <figure>5</figure> <figure>6</figure> <figure>7</figure> <figure>8</figure> <figure>9</figure> </div> </section>
现在来制作基本样式。我们给#carousel
中的每一个面设置一个20像素的间隙,可以通过left:10px
和top:10px
来实现它。这样,每一个main的有效宽度为210像素:
.container { width: 210px; height: 140px; position: relative; perspective: 1000px; } #carousel { width: 100%; height: 100%; position: absolute; transform-style: preserve-3d; } #carousel figure { display: block; position: absolute; width: 186px; height: 116px; left: 10px; top: 10px; border: 2px solid black; }
接下来,我们要旋转每一个面。#carousel
中有9个面,如果整个旋转木马的面是平均分布的,那么每个面需要在上一个面的基础上多旋转40度(360 / 9)。
#carousel figure:nth-child(1) { transform: rotateY( 0deg ); } #carousel figure:nth-child(2) { transform: rotateY( 40deg ); } #carousel figure:nth-child(3) { transform: rotateY( 80deg ); } #carousel figure:nth-child(4) { transform: rotateY( 120deg ); } #carousel figure:nth-child(5) { transform: rotateY( 160deg ); } #carousel figure:nth-child(6) { transform: rotateY( 200deg ); } #carousel figure:nth-child(7) { transform: rotateY( 240deg ); } #carousel figure:nth-child(8) { transform: rotateY( 280deg ); } #carousel figure:nth-child(9) { transform: rotateY( 320deg ); }
在接下来的事情就是移动中心点。当我们在制作立方体和长方体的时候,translate
的值很容易计算出来,基本上是等于长度和宽度或者高度的一半。对于旋转木马,我们没有尺寸可以参考,我们需要计算出每一个面的移动距离。
我们可以在纸上画一个旋转木马的草图,可以看到,我们只知道两样东西:每一个面的宽度是210像素,每一个面要在上一个面的基础上多旋转40度。从俯视图往下看,它们有9个三角形组成。如果我们在其中一个三角形上沿中心垂线将它切开,可以得到一个直角三角形。
我们可以用一个基本的切线方程确定在该图中R的长度。
经过上面的计算我们可以得出结果:每一个面需要在3D空间中向外translate
288像素。
#carousel figure:nth-child(1) { transform: rotateY( 0deg ) translateZ( 288px ); } #carousel figure:nth-child(2) { transform: rotateY( 40deg ) translateZ( 288px ); } #carousel figure:nth-child(3) { transform: rotateY( 80deg ) translateZ( 288px ); } #carousel figure:nth-child(4) { transform: rotateY( 120deg ) translateZ( 288px ); } #carousel figure:nth-child(5) { transform: rotateY( 160deg ) translateZ( 288px ); } #carousel figure:nth-child(6) { transform: rotateY( 200deg ) translateZ( 288px ); } #carousel figure:nth-child(7) { transform: rotateY( 240deg ) translateZ( 288px ); } #carousel figure:nth-child(8) { transform: rotateY( 280deg ) translateZ( 288px ); } #carousel figure:nth-child(9) { transform: rotateY( 320deg ) translateZ( 288px ); }
如果你改变了面的宽度或者数量,需要重新按照公式来计算translate
的值。另一方面来说,我们只需要知道这两个值,就可以随意改变旋转木马的面的宽度和数量,可以使用js来动态计算它们:
var tz = Math.round( ( panelSize / 2 ) / Math.tan( ( ( Math.PI * 2 ) / numberOfPanels ) / 2 ) ); // or simplified to var tz = Math.round( ( panelSize / 2 ) / Math.tan( Math.PI / numberOfPanels ) );
和3D立方体和长方体一样,要显示其他的面,只需要改变transform
的顺序即可:
transform: translateZ( -288px ) rotateY( -160deg );查看3D旋转木马-Carousel 1
学习到这里你可能觉得:
- 反复重写每一个面的
transform
样式是很无聊的事情。 - 制作旋转木马还要使用到高等数学的知识! -_-!!
每错,我们可以将单调重复的transform
样式交给脚本来完成,如果你的代码编写正确,将会比硬编码的版本更加灵活。
CSS3 3D transforms系列教程: