目录
有了上文 CSS3 旋转相册 的基础,我们再来制作一个更花哨的三维立方体旋转相册。
效果图
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 轴移动
为了保持和最终整体旋转同步,帧动画大部分时间保持不动。例如整体动画 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>

