纯css 实现3d轮播

6,339 阅读4分钟

前言

常常使用网易云音乐,看见它的首页轮播图想自己也实现一个,本文会通过 animation 结合 perspective 等 css 属性实现3d轮播的效果。让我们开始吧!

步骤

为了简单起步我们先使用三张图片,定义基础的 html 和 css 结构如下:

  1. 我们设定图片的宽度 329px ,为了凸显出中间这张图片,左右两种使用 transform:scale(0.8),然后让两边的图片的大小缩放 0.8 我们要做的就是让图片动起来就实现了轮播的效果。
  2. 动起来还只是平面的移动,为了实现3d的效果,引入 transform-styleperspective 这两个概念

接下来围绕这两点展开分析如何实现。

动起来

选用animation写动画

动起来就是动画可以通过 css animation 以及 js中的 requestAnimationFrame 这两种。我选用 animation 作为实现手段。

分析动起来的阶段

只看一张图的周期分为三个阶段也就是 左边,中间,右边,假设我们在每个阶段都停留2s,那么整个周期需要6s的时间。为了让过渡自然些,每次过渡的时候都预留0.5s过渡时间。那么过渡时间总共要1.5s 所有时间加起来需要 7.5s

animation使用

  1. 使用translateX 来实现图片 x 轴位置的移动
  2. animation-delay 支持负值,如 animation: three-D 7.5s ease -5s infinite; 表示整个过渡时间是 7.5s 由于 animation-delay 设置为 -5s 表示已经运动来 5秒也就是来到动画的 66% 的进度了。
/* 总时长是 7.5s */
@keyframes three-D {
  /* 停留2秒 */
  0%,27%{
    transform: translateX(230.3px) scale(0.8);
    z-index: 1;
  }
  /* 过渡时间为 0.5s */
  34%,61%{
    z-index: 2;
    transform: translateX(98.7px) scale(1);
  }
  /* 过渡时间为 0.5s */
  68% ,95%{
    z-index: 1;
    transform: translateX(-32.9px) scale(0.8);
  }
  /* 过渡时间为 0.5s */
  100% {
    z-index: 1;
    transform: translateX(230.3px) scale(0.8);
  }
}

设置3d效果

给他们的图片的父级设置视角,展示方式为3d。更多属性可以参考张旭鑫 CSS3 3D文章解释

  transform-style: preserve-3d;
  perspective: 800px;

使用了这个属性后,我们可以在图片的 左中上三种位置来改变他们不同的translateZ的值来实现3d的效果,其实 translateZ 就是改变图片和用户的距离,我们通过 scale(0.8) 已经达到相同的效果,因为距离用户近也就以为这图片要大。
除了改变用户的距离,我们还自定义的添加一些属性如,图片 rotateY 的角度,来实现开屏的效果。可根据自己的业务需要来添加。

完整demo地址

层级问题

当轮播图超过3张以上,拿四张来举例,一张图的周期需要划分为四个阶段。如下图分别在这四个阶段,3,4表示在同一个位置,还是和之前一样在每个阶段停留 2s 停留总时间为 8s , 1-2,2-3,4-1需要过渡时间 0.5s 总的过渡时间为 1.5s 。最终所需时间为 9.5s 。

如果还是像三张图片时只设置了 2 的层级比其他高,那么在 3,4这个阶段会出现层级问题。由于1,3,4层级相同,那么最后一张图片的时候会一直在左边的位置会一直盖住其他图片。

我采用的方式是当图片到了第四个阶段就让他的 opacity 为 0 ,那么即使最后一张图片到了第四个阶段也不会遮住上一张。

/* 总时长是 9.5s */
@keyframes three-D {
  /* 停留2秒 */
  0%,21%{
    transform: translateX(230.3px) translateZ(40px) scale(0.8);
    z-index: 3;
  }
  /* 过渡时间为 0.5s */
  26%,47%{
    z-index: 4;
    transform: translateX(98.7px) scale(1);
  }
  /* 过渡时间为 0.5s */
  51% ,73%{
    z-index: 2;
    opacity: 1;
    transform: translateX(-32.9px) scale(0.8);
  }
  /* 第三阶段图片隐藏 */
  74%,96%{
    opacity: 0;
    z-index: 1;
    transform: translateX(-32.9px) scale(0.8);
  }
  /* 过渡时间为 0.5s */
  100% {
    opacity: 1;
    z-index: 1;
    transform: translateX(230.3px) scale(0.8);
  }
}

轮播图层级问题解决demo源码

最后

通过css实现了网易云音乐轮播的效果,如果想要和轮播图有交互 会用到 animation-play-state 这个属性,如果业务有需求也可以加上。最后关于3d轮播图有好的实现方式可以在留言区评论。