实现一个在网上看到的3D平铺效果

237 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

先前在某个网站上看到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">,它的作用有三个:

  1. 设定平铺区域的大小;
  2. 设定展示元素距离视图的距离perspective,其子元素获得透视效果,可以理解为让元素具有一些3D的规律,比如说近大远小等等;
  3. 设定定位属性position,为中间<div id="imgContainer">层的绝对定位absolute提供依据,因为中间层需要进行变换,屏幕上看到的展示内容也会随之偏移,通过设定绝对定位可以使展示内容固定在一个位置。
#app {
  perspective: 3000px;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: hidden;
}

通过上面的布局和样式,可以实现以下效果: 微信截图_20220606144835.png 到这一步没什么特殊的效果,因为上面的设定样式都是为子元素服务的。

展示图片

在处理中间层之前,先处理好展示的图片。其实就是根据需要,为图片设定展示的效果,在这里将所有图片的大小设定为统一规格,让图片保持原有的比例填充满<img>标签,以及一些去其他样式,不在赘述。

.img {
  width: 100px;
  height: 130px;
  object-fit: cover;
  cursor: pointer;
  margin-top: 5px;
  border-radius: 5px;
}

通过上面的样式,将所有图片展示的规格统一起来,效果如下: 微信截图_20220606145843.png

中间层

最重要的效果处理就在这一层,包括3D的变换、<img />排布等等。

  1. 首先,需要设定图片的列数,本人将其设为3列。通过width属性和flex布局来实现,基本原理就是利用flex-wrap: wrap;,当一行排列不下时,会自动换行,所以只要将为width设定为三张图片的宽度和间隔之和,就可以实现每行三张图片,平分间隔。
#imgContainer {
  width: 315px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

效果如下: 微信截图_20220606150816.png

  1. 接下来设定3D变换,让这个图片列表“躺下”、斜放。就需要用到transform属性,通过设定xyz的旋转角度rotaterotateZ主要设定图片列表斜放的角度,rotateYrotateX主要设定图片“躺下”的效果,旋转的角度按照需求调试:
#imgContainer {
  width: 315px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  transform: rotateZ(-25deg) rotateY(30deg) rotateX(45deg);
  transform-style: preserve-3d;
}

需要注意的是旋转的顺序,不同的旋转顺序会导致最终的展示效果不同。 效果如下:
微信截图_20220606154346.png

  1. 最后在调整一下图片列表的位置,完整样式如下:
#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:

  1. 图片的浮起其实就是沿着垂直于图片正面的方向轴z轴移动,通过translateZ设定;当图片没有经过任何x轴y轴旋转时,设定该属性是看不出什么效果的;
  2. 当图片浮起之后,通过设定阴影可以增强3D效果;
  3. 当然需要在图片上添加过渡属性,变化效果看上去才不会过于突兀。 完整样式:
.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);
}