likes
comments
collection
share

简单CSS头像动画快速入门CSS 3D

作者站长头像
站长
· 阅读数 19

简单CSS头像动画快速入门CSS 3D

一个看起来非常mini的效果——鼠标经过,头像探出边框,如果你碰到这样的需求会怎么实现呢?

分析需求

正常状态下,头像图片位于相框之内。当鼠标悬停时,头像变大并且上半部分压住相框,下半部分依然在相框内。这样就产生了探出头的效果。也就是在鼠标悬停时实现下图第3个图片的效果。

简单CSS头像动画快速入门CSS 3D

学习了两位css-tricks大佬的文章后(地址附在文末),我学会了两种纯CSS的实现方式。

CSS 3D 实现

个人更喜欢3D的实现方式,通过这个简单动画,更加深入的学习了CSS 3D。

首先需要了解CSS的三维坐标系,记住3个轴的正负值方向。刚开始我记错了三维坐标系的方向,理解3D变换就很晕 😇 ,记住坐标系之后就很好理解每个轴上正负值变化以及旋转的效果。

简单CSS头像动画快速入门CSS 3D

  • x轴 : 水平向右,x右边是正值,左边是负值
  • y轴 : 垂直向下,y下面是正值,上面是负值
  • z轴 : 垂直屏幕,往外面是正值,往里面是负值

只需一个html标签

没错,只需要一个div

 <div class="d3"></div>

CSS

画出基本形态

简单CSS头像动画快速入门CSS 3D

之所以只用到一个div,因为我们可以用::after和::before这两个伪元素打配合。

::before画出边框,::after放头像图片

.d3 {
  position: relative; 
  width: 200px; height: 200px;
  background-color: lightpink;
  border-radius: 100%;
}

.d3::before {
  position: absolute;bottom:0;
  content: '';
  width: 100%; height: 100%;
  border: 6px solid green;
  border-radius: 100%;
}

.d3::after {
  content: '';
  position: absolute; bottom:0;
  background: url(~/assets/images/avatar2.png) no-repeat center 100%;
  background-size: 90%;
  width: 100%; height: 100%;
  border-radius: 0 0 900px 900px;
}

现在小丸子还是在相框外面,怎么让她进去?接下来是关键!!!

transform-style: preserve-3d

transform-style接受两个值

  • flat:设置元素的子元素位于该元素的平面中(子元素不设置3D空间)
  • perserve-3d:设置元素的子元素应用于3D空间中

简单CSS头像动画快速入门CSS 3D

既然要用到3D,首先需要告诉浏览器给我们准备好3D空间,我们先给div加上

.d3 { 
    transform-style: preserve-3d;
    ...
}

rotate3d

为了让小丸子头像上半部分在相框之上,下半部分在边框之下,我们让她绕着X轴旋转一下

transform: rotateX(-10deg);

rotate3d()  CSS 函数定义一个变换,它将元素围绕固定轴移动而不使其变形。运动量由指定的角度定义; 如果为正,运动将为顺时针,如果为负,则为逆时针。

此处只需要绕X轴旋转,所以使用rotateX

头像旁用CSS画了一个示意图,能够更直观的看出两个元素在空间中的位置

简单CSS头像动画快速入门CSS 3D

不过这个时候,小丸子头像的下部被粉色背景遮挡了。因为在旋转时,上半部分透了出来,而下半部分退到父元素后面去了。没关系我们继续

translate

我们给::before和::after都加上,这样头像和相框都会在Z轴上往前移动,不会再被粉色背景(div)元素遮挡。

translate: 0 0 30px;

CSS 属性 translate 允许你单独声明平移变换,并独立于 transform 属性。这在一些典型的用户界面上更好用,而且这样就无需在 transform 中声明该函数并记住转换函数的确切顺序了。

简单CSS头像动画快速入门CSS 3D

鼠标悬停放大

修改小丸子伪元素的height和background-size让头像变大,

width需要和相框伪元素保持一致,因为用border-radius实现圆角,如果2个元素width不一致,下边的圆弧半径就会不同,效果不太好。

// 悬停状态
.d3:hover::after {
  width: 95%;
  height: 115%;
  left: 2.5%;
  background-size: 115%;
}
.d3:hover::before {
  transform: scale(0.95) translateY(2.5%);
}

transform-origin

transform-origin CSS 属性让你更改一个元素变形的原点

这张小丸子头像选的不是很好,脑袋太大了,如果悬停时放大百分比比较大,头发就会被遮挡一部分。所以额外给::after再增加一个样式,让旋转的原点靠下一点。

transform-origin: 50% 60%;

现在差不多可以了,但是我给div加了一个粉色背景,又在悬停时缩小了相框,所以还有点问题,悬停时背景漏出来不好看。

简单CSS头像动画快速入门CSS 3D

如果不需要背景,那么没事了,想要保留背景的话,我们还需要处理一下。

perspective

给div加上透视效果

transform: perspective(450px);

CSS 属性 perspective 指定了观察者与 z=0 平面的距离,使具有三维位置变换的元素产生透视效果。z>0 的三维元素比正常大,而 z<0 时则比正常小,大小程度由该属性的值决定。

perspective可能比较难理解一些,它就像绘画里面的透视效果,远小近大。perspetive的值越小,透视效果就越明显。我们只要记住相同perspective属性值,同样大小的元素,在Z轴上越往前(正值变大)屏幕上显示越大,反之显示变小。

简单CSS头像动画快速入门CSS 3D

我们给相框和图片设置了translate: 0 0 30px 让它们在z轴下往前走,在屏幕上它们会变大,div相对就小了,在放大时也不会漏出来(具体取值可以根据实际情况调整)。

虽然这个效果很不起眼,但是完整的走一遍,让我入门了CSS 3D,只能说CSS越来越强大了。

CSS源码

最后放上完整的CSS代码

.d3 {
  margin-left: 100px;

  transform-style: preserve-3d;
  transform: perspective(450px);
  position: relative;
  width: 200px;
  height: 200px;
  background-color: lightpink;
  border-radius: 100%;
}

.d3::before {
  display: block;
  position: absolute;
  bottom: 0;

  content: '';
  width: 100%;
  height: 100%;
  border: 6px solid green;
  border-radius: 100%;
  transition: transform 0.15s ease-in-out;
  transform-style: preserve-3d;
  perspective: 450px;
  translate: 0 0 30px;
}

.d3::after {
  content: '';
  position: absolute;
  background: url(~/assets/images/avatar2.png) no-repeat center 100%;
  background-size: 90%;
  width: 100%;
  height: 100%;
  border-radius: 0 0 900px 900px;
  display: block;
  left: 0;
  bottom: 0;
  transform: rotateX(-10deg);
  transform-origin: 50% 60%;
  transition: 0.15s ease-in-out;
  translate: 0 0 30px;
}

// 悬停状态
.d3:hover::after {
  width: 95%;
  height: 115%;
  left: 2.5%;
  background-size: 115%;
}
.d3:hover::before {
  transform: scale(0.95) translateY(2.5%);
}

不用3D的实现方式

简单CSS头像动画快速入门CSS 3D

红色边框是另一种实现方式,代码量更少。这里只贴源码,大家有兴趣可以看作者的原文 《Fancy Hover Effect For Your Avatar》

<img src="~/assets/images/avatar2.png" />
img {
  --s: 200px; /* image size */
  --b: 6px; /* border thickness */
  --c: var(--el-color-danger); /* border color */
  --cb: #e9ecef; /* background color */
  --f: 1; /* initial scale */

  box-sizing: content-box;
  width: var(--s);
  height: var(--s);
  aspect-ratio: 1;
  padding-top: calc(var(--s) / 5);
  cursor: pointer;
  border-radius: 0 0 999px 999px;
  --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box;
  --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));
  outline: var(--b) solid var(--c);
  outline-offset: var(--_o);
  background: radial-gradient(
      circle closest-side,
      var(--cb) calc(99% - var(--b)),
      var(--c) calc(100% - var(--b)) 99%,
      #0000
    )
    var(--_g);
  -webkit-mask: linear-gradient(#000 0 0) no-repeat 50% calc(1px - var(--_o)) /
      calc(100% / var(--f) - 2 * var(--b) - 2px) 50%,
    radial-gradient(circle closest-side, #000 99%, #0000) var(--_g);
  transform: scale(var(--f));
  transition: 0.5s;
}
img:hover {
  --f: 1.2; /* hover scale */
}

参考文章: