CSS3 3D立方体旋转相册

本文介绍了如何用简短的 CSS3 3d transform、animation 等属性来一步步制作心仪女神的 3D 立方体旋转相册,用来表白或是恋爱纪念都是非常合适滴。

有了上文 CSS3 旋转相册 的基础,我们再来制作一个更花哨的三维立方体旋转相册。

效果图

3D 旋转立方体女神相册

2 步实现 3D立方体旋转效果

设置三维空间

body 内添加如下代码,结构:舞台,容器,图片占位符(这里用 div 而不用 img,主要是方便测试,给 div 加个纯色默认背景图,就容易找出哪个图片路径失效了)

HTML
<div class="stage-area">
  <div class="container">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>
</div>
  • 初始化 html、body 样式
  • 设置舞台 stage-area 高度、相对定位,透视距离
  • 设置容器 container 宽高并定位与舞台中央
  • 设置图片宽高,绝对定位,叠加在一起
CSS
html,
body {
  background-color: black;
  height: 100%;
  margin: 0;
}
.stage-area {
  min-height: 100%;
  position: relative;
  perspective: 5000px;
}
.container {
  width: 200px;
  height: 200px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -80px;
  margin-left: -100px;
}
.container div {
  width: 200px;
  height: 200px;
  position: absolute;
}
.container div:nth-child(1) {
  background: purple url(./img/1.jpg) no-repeat center / cover;
}
.container div:nth-child(2) {
  background: dodgerblue url(./img/7.jpg) no-repeat center / cover;
}
.container div:nth-child(3) {
  background: chartreuse url(./img/2.jpg) no-repeat center / cover;
}
.container div:nth-child(4) {
  background: peru url(./img/4.jpg) no-repeat center / cover;
}
.container div:nth-child(5) {
  background: skyblue url(./img/6.jpg) no-repeat center / cover;
}
.container div:nth-child(6) {
  background: yellow url(./img/8.jpg) no-repeat center / cover;
}

接下来重点设置 CSS3 3D 相关属性

  • 设置舞台 stage-area,三维透视,三维变换,稍微沿着 X 轴向下翻折一点角度,这样一开始旋转时,不止能看到立方体的一个正面,也能开到侧边的一点

2 段动画

6 张图片构建立方体

现在是 6 张图片重叠在一起,如何构建立方体呢?

  • 第 1 张图,保持不变,也就是立方体的正面图
  • 第 2 张图,向左平移出,再沿着右边向后折叠 90 度
  • 第 3 张图,向右平移出,再沿着左边向后折叠 90 度
  • 同理 …
  • 第 6 张图,直接向后平移,即 Z 轴移动
CSS3 构造立方体过程

为了保持和最终整体旋转同步,帧动画大部分时间保持不动。例如整体动画 10s,前 2s 就完成立方体构造,8 秒保持不动,等待旋转完成,再重新构造一遍立方体。

CSS
@keyframes left {
  10% {
    transform: translateX(-200px);
  }
  20% {
    transform: translateX(-200px) rotateY(-90deg);
  }
  100% {
    transform: translateX(-200px) rotateY(-90deg);
  }
}
@keyframes right {
  10% {
    transform: translateX(200px);
  }
  20% {
    transform: translateX(200px) rotateY(90deg);
  }
  100% {
    transform: translateX(200px) rotateY(90deg);
  }
}
@keyframes top {
  10% {
    transform: translateY(-200px);
  }
  20% {
    transform: translateY(-200px) rotateX(90deg);
  }
  100% {
    transform: translateY(-200px) rotateX(90deg);
  }
}
@keyframes bottom {
  10% {
    transform: translateY(200px);
  }
  20% {
    transform: translateY(200px) rotateX(-90deg);
  }
  100% {
    transform: translateY(200px) rotateX(-90deg);
  }
}
@keyframes back {
  20% {
    transform: translateZ(-200px);
  }
  to {
    transform: translateZ(-200px);
  }
}


.container div:nth-child(1) {
  ...
  transform-origin: right center;
  animation: left 5s ease forwards;
}
.container div:nth-child(2) {
  ...
  transform-origin: left center;
  animation: right 5s ease forwards;
}
.container div:nth-child(3) {
  ...
  transform-origin: bottom center;
  animation: top 5s ease forwards;
}
.container div:nth-child(4) {
  ...
  transform-origin: top center;
  animation: bottom 5s ease forwards;
}
.container div:nth-child(5) {
  ...
}
.container div:nth-child(6) {
  ...
  animation: back 5s ease forwards;
}
 .container div:nth-child(n) {
  animation-duration: 5s; /* 方便统一改 */
}

旋转立方体

我们需要把 container 作为一个整体 transform,以便能看到立方体的每个面。

注意:如果需要调整动画时间,最好跟上面动画时间保持一致。

CSS
@keyframes container {
  10% {
    transform: rotateY(-90deg);
  }
  20% {
    transform: rotateY(-180deg);
  }
  30% {
    transform: rotateY(-270deg);
  }
  40% {
    transform: rotateY(-330deg);
  }
  50% {
    transform: rotateX(90deg);
  }
  60% {
    transform: rotateX(180deg);
  }
  70% {
    transform: rotateX(270deg);
  }
  80% {
    transform: rotateX(360deg);
  }
  90% {
    transform: rotateY(90deg);
  }
  100% {
    transform: rotateX(180deg);
  }
}

.container {
  ...
  transform-style: preserve-3d;
  transform-origin: center center -100px;
  animation: container 4s 1s ease-in-out infinite;
}

最后略微调整一下舞台的角度,稍微沿着 X 轴向下翻折一点角度,这样一开始旋转时,不止能看到立方体的一个正面,也能开到侧边多个面。

CSS
.stage-area {
  ...
  transform-style: preserve-3d;
  transform: rotateX(-30deg);
}

完整代码

HTML
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>3D 旋转立方体 - dalaobb.com</title>
    <style>
      @keyframes left {
        10% {
          transform: translateX(-200px);
        }
        20% {
          transform: translateX(-200px) rotateY(-90deg);
        }
        100% {
          transform: translateX(-200px) rotateY(-90deg);
        }
      }
      @keyframes right {
        10% {
          transform: translateX(200px);
        }
        20% {
          transform: translateX(200px) rotateY(90deg);
        }
        100% {
          transform: translateX(200px) rotateY(90deg);
        }
      }
      @keyframes top {
        10% {
          transform: translateY(-200px);
        }
        20% {
          transform: translateY(-200px) rotateX(90deg);
        }
        100% {
          transform: translateY(-200px) rotateX(90deg);
        }
      }
      @keyframes bottom {
        10% {
          transform: translateY(200px);
        }
        20% {
          transform: translateY(200px) rotateX(-90deg);
        }
        100% {
          transform: translateY(200px) rotateX(-90deg);
        }
      }
      @keyframes back {
        20% {
          transform: translateZ(-200px);
        }
        to {
          transform: translateZ(-200px);
        }
      }
      @keyframes container {
        10% {
          transform: rotateY(-90deg);
        }
        20% {
          transform: rotateY(-180deg);
        }
        30% {
          transform: rotateY(-270deg);
        }
        40% {
          transform: rotateY(-330deg);
        }
        50% {
          transform: rotateX(90deg);
        }
        60% {
          transform: rotateX(180deg);
        }
        70% {
          transform: rotateX(270deg);
        }
        80% {
          transform: rotateX(360deg);
        }
        90% {
          transform: rotateY(90deg);
        }
        100% {
          transform: rotateX(180deg);
        }
      }
      html,
      body {
        background-color: black;
        height: 100%;
        margin: 0;
      }
      .stage-area {
        min-height: 100%;
        position: relative;
        perspective: 5000px;
        transform-style: preserve-3d;
        transform: rotateX(-30deg);
      }
      .container {
        width: 200px;
        height: 200px;
        position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -80px;
        margin-left: -100px;
        transform-style: preserve-3d;
        transform-origin: center center -100px;
        animation: container 4s 1s ease-in-out infinite;
      }
      .container div {
        width: 200px;
        height: 200px;
        position: absolute;
      }
      .container div:nth-child(1) {
        background: purple url(./img/1.jpg) no-repeat center / cover;
        transform-origin: right center;
        animation: left 5s ease infinite forwards;
      }
      .container div:nth-child(2) {
        background: dodgerblue url(./img/7.jpg) no-repeat center / cover;
        transform-origin: left center;
        animation: right 5s ease infinite forwards;
      }
      .container div:nth-child(3) {
        background: chartreuse url(./img/2.jpg) no-repeat center / cover;
        transform-origin: bottom center;
        animation: top 5s ease infinite forwards;
      }
      .container div:nth-child(4) {
        background: peru url(./img/4.jpg) no-repeat center / cover;
        transform-origin: top center;
        animation: bottom 5s ease infinite forwards;
      }
      .container div:nth-child(5) {
        background: skyblue url(./img/6.jpg) no-repeat center / cover;
      }
      .container div:nth-child(6) {
        background: yellow url(./img/8.jpg) no-repeat center / cover;
        animation: back 5s ease infinite forwards;
      }
      .container div:nth-child(n) {
        animation-duration: 5s;
      }
    </style>
  </head>
  <body>
    <div class="stage-area">
      <div class="container">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
    </div>
  </body>
</html>