本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
先前在某个网站上看到3D的平铺图片列表,觉得十分惊艳,于是试着自己动手复现一下那个效果,本文记叙一下整体思路。
效果
代码
HTML布局如下:
<div id="app">
<div id="imgContainer">
<img class="img" src="xxxxxxxxxxxxxxxxx" />
<img class="img" src="xxxxxxxxxxxxxxxxx" />
<img class="img" src="xxxxxxxxxxxxxxxxx" />
......
</div>
</div>
通过上面的布局,可以看到一共有三层元素:最外层的<div id="app">、中间的<div id="imgContainer">、展示内容的<img>。这三层的主要功能各不相同,稍后再说,其中展示内容也可以更换成其他标签,只要实现想要的效果即可。
样式设定
最外层
最外层是<div id="app">,它的作用有三个:
- 设定平铺区域的大小;
- 设定展示元素距离视图的距离
perspective,其子元素获得透视效果,可以理解为让元素具有一些3D的规律,比如说近大远小等等; - 设定定位属性
position,为中间<div id="imgContainer">层的绝对定位absolute提供依据,因为中间层需要进行变换,屏幕上看到的展示内容也会随之偏移,通过设定绝对定位可以使展示内容固定在一个位置。
#app {
perspective: 3000px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
}
通过上面的布局和样式,可以实现以下效果:
到这一步没什么特殊的效果,因为上面的设定样式都是为子元素服务的。
展示图片
在处理中间层之前,先处理好展示的图片。其实就是根据需要,为图片设定展示的效果,在这里将所有图片的大小设定为统一规格,让图片保持原有的比例填充满<img>标签,以及一些去其他样式,不在赘述。
.img {
width: 100px;
height: 130px;
object-fit: cover;
cursor: pointer;
margin-top: 5px;
border-radius: 5px;
}
通过上面的样式,将所有图片展示的规格统一起来,效果如下:
中间层
最重要的效果处理就在这一层,包括3D的变换、<img />排布等等。
- 首先,需要设定图片的列数,本人将其设为3列。通过
width属性和flex布局来实现,基本原理就是利用flex-wrap: wrap;,当一行排列不下时,会自动换行,所以只要将为width设定为三张图片的宽度和间隔之和,就可以实现每行三张图片,平分间隔。
#imgContainer {
width: 315px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
效果如下:
- 接下来设定3D变换,让这个图片列表“躺下”、斜放。就需要用到
transform属性,通过设定x、y、z的旋转角度rotate。rotateZ主要设定图片列表斜放的角度,rotateY和rotateX主要设定图片“躺下”的效果,旋转的角度按照需求调试:
#imgContainer {
width: 315px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
transform: rotateZ(-25deg) rotateY(30deg) rotateX(45deg);
transform-style: preserve-3d;
}
需要注意的是旋转的顺序,不同的旋转顺序会导致最终的展示效果不同。 效果如下:
- 最后在调整一下图片列表的位置,完整样式如下:
#imgContainer {
position: absolute;
top: 0;
bottom: 0;
transform: translateY(-70px) rotateZ(-25deg) rotateY(30deg) rotateX(45deg);
transform-style: preserve-3d;
width: 315px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
展示图片的鼠标悬浮效果
可以看到上面的示例,鼠标悬浮时,图片有一种浮起的效果,实现这种效果主要依靠阴影box-shadow和变换transform:
- 图片的浮起其实就是沿着垂直于图片正面的方向轴
z轴移动,通过translateZ设定;当图片没有经过任何x轴、y轴旋转时,设定该属性是看不出什么效果的; - 当图片浮起之后,通过设定阴影可以增强3D效果;
- 当然需要在图片上添加过渡属性,变化效果看上去才不会过于突兀。 完整样式:
.img {
width: 100px;
height: 130px;
background: skyblue;
object-fit: cover;
cursor: pointer;
transition: all 0.5s;
margin-top: 5px;
border-radius: 5px;
}
.img:hover {
transform: translateZ(10px);
box-shadow: -15px 25px 0px rgb(0 0 0/0.6);
}