一步一步来制作CSS3 3D旋转相册

  • body 内添加如下代码,结构:舞台,容器,图片内容
<div class="stage-area">
    <div class="container">
        <a href="#"><img src="1.jpeg" /></a>
        <a href="#"><img src="2.jpeg" /></a>
        <a href="#"><img src="3.jpeg" /></a>
        <a href="#"><img src="4.jpeg" /></a>
        <a href="#"><img src="5.jpeg" /></a>
        <a href="#"><img src="6.jpeg" /></a>
        <a href="#"><img src="7.jpeg" /></a>
        <a href="#"><img src="8.jpeg" /></a>
        <a href="#"><img src="9.jpeg" /></a>
    </div>
</div>
  • 设置舞台透视距离。设置容器3D透视和内容宽度。设置图片最大伸缩到自身宽度,这里说下 max-width:100% 与 width:100% 的区别,前者图片最大伸展到图片实际的宽度,后者伸展最大伸展到父级元素的宽度,也就是说如果父级的宽度超过图片的宽度后者会拉伸超过图片实际宽度导致模糊失真,这是响应式或做自适应时默认要设置的属性。
.stage-area {
    perspective: 800px;
}
.container {
    transform-style: preserve-3d;
    width: 160px;
}
img {
    max-width: 100%;
}
  • 设置容器相对于窗口水平垂直居中,图片叠加在一起的效果。利用定位和负的margin来水平垂直居中确定宽度的块级元素。设置图片绝对定位使得图片相互叠加,避免后续导致的DNA螺旋效果,也方便查看垂直居中效果。
.container {
    ...
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -80px;
    margin-left: -80px;
}
img {
    ...
    position: absolute;
}
  • 查看并未达到预期的垂直居中效果,图片也被裁剪。查看页面元素发现body高度为0,这是由于内容设置了绝对定位脱离了普通流而且块级元素的默认性质是宽度尽量宽撑满,高度尽量窄由内容高度决定。设置如下:
html, body {
    height: 100%;
}
.stage-area {
    ...
    min-height: 100%;
}
  • 设置图片旋转角度,此时发现有种翻书效果。
.container a:nth-child(1) img {
    transform: rotateY(0deg);
}
.container a:nth-child(2) img {
    transform: rotateY(40deg);
}
.container a:nth-child(3) img {
    transform: rotateY(80deg);
}
.container a:nth-child(4) img {
    transform: rotateY(120deg);
}
.container a:nth-child(5) img {
    transform: rotateY(160deg);
}
.container a:nth-child(6) img {
    transform: rotateY(200deg);
}
.container a:nth-child(7) img {
    transform: rotateY(240deg);
}
.container a:nth-child(8) img {
    transform: rotateY(280deg);
}
.container a:nth-child(9) img {
    transform: rotateY(320deg);
}

这里写图片描述
- 设置图片3D Z轴距离


.container a:nth-child(1) img {
    transform: rotateY(0deg) translateZ(250px);
}
.container a:nth-child(2) img {
    transform: rotateY(40deg) translateZ(250px);
}
...

这里写图片描述
- 好了,一个3D立体的旋转相册出现了,如果感觉图片有点太高,有种仰视的感觉,可以设置perspective-origin,让透视点高一点,产生俯瞰的效果。

这里写图片描述

.stage-area {
    ...
    perspective-origin: center 30%;
}
  • 去掉图片定位,可以看下DNA螺旋效果,后面动态旋转的时候可以倒腾看看。
    这里写图片描述

  • 接下来,让图片动起来,也就是绕着3D视图的Y轴旋转,这就得靠 @keyframes 设置关键帧和 animation 了。

属性 描述
@keyframes 定义关键帧
animation 所有动画属性的简写属性,除了 animation-play-state 属性。
animation-name @keyframes 定义的动画名称。
animation-duration 设置完成动画所花费的时间。默认值是 0,意味着没有动画效果。
animation-timing-function 使用名为三次贝塞尔(Cubic Bezier)函数的数学函数,来生成速度曲线。能够在该函数中使用自己的值。
animation-delay 设置动画开始前等待的时间,以秒或毫秒计。默认值是 0。
animation-iteration-count 设置动画被播放的次数。
animation-direction 设置动画是否在下一周期逆向地播放,单数次正向,偶数次逆向。
animation-fill-mode 设置动画在播放之前或之后,其动画效果是否可见。
animation-play-state 设置动画正在运行或暂停。
@keyframes rotating {
    0% {
        transform: rotateY(0deg);
    }
    100% {
        transform: rotateY(360deg);
    }
}
.container {
    ...
    /*animation: rotating 10s linear 3s infinite alternate forwards;*/
    animation-name: rotating;
    animation-duration: 10s;
    animation-timing-function: linear;
    /*animation-delay: 3s;*/
    animation-iteration-count: infinite;
    /*animation-direction: alternate;*/
    /*animation-fill-mode: forwards;*/
}

这里写图片描述

  • DNA螺旋效果
    这里写图片描述

  • 如果我们想鼠标移动到图片上,就暂停动画该怎么办呢,设置 animation-play-state ,同时为了美观,给图片加个半透明小边框。

.container:hover {
    animation-play-state: paused;
}
.container img {
    border: 3px solid rgba(255, 255, 255, .5);
}
  • 还想更进一步,实现点击图片大图显示效果,这时可以利用 position + z-index + :target 伪类来实现。修改页面元素:
<img id="t2" src="2.jpeg" />
<img id="t3" src="3.jpeg" />
<img id="t4" src="4.jpeg" />
<img id="t5" src="5.jpeg" />
<img id="t6" src="6.jpeg" />
<img id="t7" src="7.jpeg" />
<img id="t8" src="8.jpeg" />
<img id="t9" src="9.jpeg" />
<img id="t1" src="1.jpeg" />
<div class="stage-area">
    <div class="container">
        <a href="#t1"><img src="1.jpeg" /></a>
        <a href="#t2"><img src="2.jpeg" /></a>
        <a href="#t3"><img src="3.jpeg" /></a>
        <a href="#t4"><img src="4.jpeg" /></a>
        <a href="#t5"><img src="5.jpeg" /></a>
        <a href="#t6"><img src="6.jpeg" /></a>
        <a href="#t7"><img src="7.jpeg" /></a>
        <a href="#t8"><img src="8.jpeg" /></a>
        <a href="#t9"><img src="9.jpeg" /></a>
    </div>
</div>
  • 此时发现一个有意思的现象,图片外沿出现缝隙,我们知道谷歌浏览器默认给 body 加了 margin ,img 设置了绝对定位但没设置top,left属性,给 body 添加 border 和 padding 发现图片定位于 body 的 content 区域边界,如果设置图片top: 0; left: 0;发现此时图片与浏览器窗口边界对齐。可以设置 body margin: 0 或 图片定位top: 0; left: 0;来消除缝隙。
    这里写图片描述
  • 我们要如何实现点击图片切换后面的大图呢?原理:相册图片有 a 元素包裹,href 属性对应大图的 id,此时点击相册图片可以触发大图 :target 的伪类样式,由于图片都设置了 position 定位,可以设置图片的 z-index 来实现层级升降。之前定位图片是按顺序叠加的,有个小技巧,可以把首次要展示的图片放下面的位置。如下:降低非 :target 的图片的层级。
body > img:not(:target) {
    z-index: -1;
}

这里写图片描述

  • 至此大功告成,但也在过程中发现了不少问题,比如刚开始是尝试在 提高 .container 层级降低图片层级,但失败了。查询资料,可能是在 .stage-area 设置了 perspective 属性产生了新的层级层叠上下文,导致 .container 和大图不在一个层级层叠上下文中,导致 z-index 失败,去掉 perspective 相关属性测试发现正常。
.container {
    ...
    z-index: 3;
}
body > img:not(:target) {
    z-index: 1;
}
body > img:target {
    z-index: 2;
}
  • 完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>旋转相册</title>
    <style>
        @keyframes rotating {
            0% {
                transform: rotateY(0deg);
            }
            100% {
                transform: rotateY(360deg);
            }
        }
        html, body {
            height: 100%;
            margin: 0;
        }
        .stage-area {
            perspective: 800px;
            min-height: 100%;
            perspective-origin: center 30%;
        }
        .container {
            transform-style: preserve-3d;
            width: 160px;
            position: absolute;
            /*z-index: 3;*/
            top: 50%;
            left: 50%;
            margin-top: -80px;
            margin-left: -80px;
            /*animation: rotating 10s linear 3s infinite alternate forwards;*/
            animation-name: rotating;
            animation-duration: 10s;
            animation-timing-function: linear;
            /*animation-delay: 3s;*/
            animation-iteration-count: infinite;
            /*animation-direction: alternate;*/
            /*animation-fill-mode: forwards;*/
        }
        .container:hover {
            animation-play-state: paused;
        }
        .container img {
            border: 3px solid rgba(255, 255, 255, .5);
        }
        img {
            max-width: 100%;
            position: absolute;
        }
        .container a:nth-child(1) img {
            transform: rotateY(0deg) translateZ(250px);
        }
        .container a:nth-child(2) img {
            transform: rotateY(40deg) translateZ(250px);
        }
        .container a:nth-child(3) img {
            transform: rotateY(80deg) translateZ(250px);
        }
        .container a:nth-child(4) img {
            transform: rotateY(120deg) translateZ(250px);
        }
        .container a:nth-child(5) img {
            transform: rotateY(160deg) translateZ(250px);
        }
        .container a:nth-child(6) img {
            transform: rotateY(200deg) translateZ(250px);
        }
        .container a:nth-child(7) img {
            transform: rotateY(240deg) translateZ(250px);
        }
        .container a:nth-child(8) img {
            transform: rotateY(280deg) translateZ(250px);
        }
        .container a:nth-child(9) img {
            transform: rotateY(320deg) translateZ(250px);
        }
        body > img:not(:target) {
            z-index: -1;
        }
        /*body > img:not(:target) {
             z-index: 1;
         }
        body > img:target {
            z-index: 2;
        }*/
    </style>
</head>
<body>
<img id="t2" src="2.jpeg" />
<img id="t3" src="3.jpeg" />
<img id="t4" src="4.jpeg" />
<img id="t5" src="5.jpeg" />
<img id="t6" src="6.jpeg" />
<img id="t7" src="7.jpeg" />
<img id="t8" src="8.jpeg" />
<img id="t9" src="9.jpeg" />
<img id="t1" src="1.jpeg" />
<div class="stage-area">
    <div class="container">
        <a href="#t1"><img src="1.jpeg" /></a>
        <a href="#t2"><img src="2.jpeg" /></a>
        <a href="#t3"><img src="3.jpeg" /></a>
        <a href="#t4"><img src="4.jpeg" /></a>
        <a href="#t5"><img src="5.jpeg" /></a>
        <a href="#t6"><img src="6.jpeg" /></a>
        <a href="#t7"><img src="7.jpeg" /></a>
        <a href="#t8"><img src="8.jpeg" /></a>
        <a href="#t9"><img src="9.jpeg" /></a>
    </div>
</div>
</body>
</html>

参考资料:
1、十天精通CSS3
https://www.imooc.com/code/1882
2、深入理解CSS中的层叠上下文和层叠顺序
https://www.zhangxinxu.com/wordpress/2012/09/css3-3d-transform-perspective-animate-transition/
3、理解 CSS z-index
https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
4、CSS3 动画属性(Animation)
http://www.w3school.com.cn/cssref/index.asp#animation

猜你喜欢

转载自blog.csdn.net/guduyibeizi/article/details/80790109