轮播

轮播

前端开发者在内容轮播的实现上有无数种选择。我可以建议Flickity吗?(译者注:Flickity这个插件的作者也是本书作者)现在我们有了浏览器里的3D能力,为什么我们不去创建一个真实的3D轮播来试一把呢?

这个例子的HTML结构与盒子、立方体、卡片翻转的一样,接下来我们会将它变得更有趣,做一个含有9个卡片的轮播。

<div class="scene">
  <div class="carousel">
    <div class="carousel__cell">1</div>
    <div class="carousel__cell">2</div>
    <div class="carousel__cell">3</div>
    <div class="carousel__cell">4</div>
    <div class="carousel__cell">5</div>
    <div class="carousel__cell">6</div>
    <div class="carousel__cell">7</div>
    <div class="carousel__cell">8</div>
    <div class="carousel__cell">9</div>
  </div>
</div>

现在我们加一些基础的布局样式。我们通过left: 10px让卡片与卡片间隔20px,所以每一个卡片的有效宽度保持210px不变。

.scene {
  width: 210px;
  height: 140px;
  position: relative;
  perspective: 1000px;
}

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

.carousel__cell {
  position: absolute;
  width: 190px;
  height: 120px;
  left: 10px;
  top: 10px;
}

接下来旋转每一个卡片。这个轮播含有9个卡片,如果要使卡片们在轮播中平均分布,那么每一张卡片需要相对下一张旋转40°角(360 / 9)。

.carousel__cell:nth-child(1) { transform: rotateY(  0deg); }
.carousel__cell:nth-child(2) { transform: rotateY( 40deg); }
.carousel__cell:nth-child(3) { transform: rotateY( 80deg); }
.carousel__cell:nth-child(4) { transform: rotateY(120deg); }
.carousel__cell:nth-child(5) { transform: rotateY(160deg); }
.carousel__cell:nth-child(6) { transform: rotateY(200deg); }
.carousel__cell:nth-child(7) { transform: rotateY(240deg); }
.carousel__cell:nth-child(8) { transform: rotateY(280deg); }
.carousel__cell:nth-child(9) { transform: rotateY(320deg); }

现在该将平面向外平移了。回想做立方体、长方体的时候,向外平移的值很好计算,也就是等于长、宽、高的一半。而轮播这个例子里,我们没有一个具体的值可以直接参考,下面我们通过其他的方法来计算这个平移距离。

下面画出了一个轮播图示,我们看到我们已知的两个信息:每个卡片的宽度是210px,并且相对其相邻卡片旋转40°角。如果我们从其中一个三角形的中心切开,我们会得到一个三角学里的重要内容,直角三角形。

通过这个图示,我们可以用基本的正切等式来计算出 r 的长度。

现在我们有了卡片在3D空间内向外平移的距离,288px

.carousel__cell:nth-child(1) { transform: rotateY(  0deg) translateZ(288px); }
.carousel__cell:nth-child(2) { transform: rotateY( 40deg) translateZ(288px); }
.carousel__cell:nth-child(3) { transform: rotateY( 80deg) translateZ(288px); }
.carousel__cell:nth-child(4) { transform: rotateY(120deg) translateZ(288px); }
.carousel__cell:nth-child(5) { transform: rotateY(160deg) translateZ(288px); }
.carousel__cell:nth-child(6) { transform: rotateY(200deg) translateZ(288px); }
.carousel__cell:nth-child(7) { transform: rotateY(240deg) translateZ(288px); }
.carousel__cell:nth-child(8) { transform: rotateY(280deg) translateZ(288px); }
.carousel__cell:nth-child(9) { transform: rotateY(320deg) translateZ(288px); }

如果我们想去改变卡片的宽度或者数量时,我们只需要将这两个变量传入等式,进而得到一个合适的traslateZ的值。在JS中,这个等式应该是这样:

var tz = Math.round( ( cellSize / 2 ) /
  Math.tan( ( ( Math.PI * 2 ) / numberOfCells ) / 2 ) );
// or simplified to
var tz = Math.round( ( cellSize / 2 ) /  Math.tan( Math.PI / numberOfCells ) );

类似我们之前的例子,为了展示每一个面,我们仅需要将相反的变换样式应用在轮播上即可。

/* 展示第五张卡片 */
.carousel {
  transform: translateZ(-288px) rotateY(-160deg);
}

在3D轮播中使用JavaScript

现在你可能会想,为卡片重写转换样式是一件很无聊的事情,没错。刚好3D对象的重复特性更便于JS脚本化,我们可以将所有乏味枯燥的转换样式移到JS中,如果做好了,那么这将会比CSS里的硬编码更加适合扩展。

我们不仅可以改变卡片的数量,甚至可以从水平到垂直来改变轮播的方向。Perfect for The Price is Right wheel.

最后更新于