写点什么

一个炫酷的头像悬停效果 2

作者:南城FE
  • 2023-08-21
    广东
  • 本文字数:2571 字

    阅读完需:约 8 分钟

基于上次翻译的 🔥🔥一个炫酷的头像悬停效果 收获了不少同学的喜欢,原作者近期进行了优化升级。本文将升级后的核心实现过程进行梳理讲解,如果没看过第一期的推荐先看看第一期的实现过程。升级后的效果如下图所示。



gif 动画效果如下:



相对于上次的效果主要增加了背景的变化,增加了默认的旋转动画以及背景花瓣的效果。核心实现技术点如下:


  • 不需要额外的元素,仅使用<img>标签

  • 不使用伪元素

  • 使用 future CSS,mask,@property,三角函数和大量的数学函数

  • 使用 Sass 和 CSS 变量优化代码量

  • 小圆的大小和数量可配置


对于实现过程的相关三角函数及 Sass 相关函数不过多解析,有兴趣的可以详细了解。

基础变量定义

为了方便后面操作与更改配置,首先定义几个变量方便调整配置和后续代码引用。


背景圆中的小圆数量 $n


$n: 15;
复制代码


控制小圆半径和主体的尺寸大小:


--r: 50px; 
复制代码


控制小圆放大比例基数,控制数值在 1.2 和 2 之间:


--f: 2;
复制代码


主体背景颜色:


--c: #E4844A;
复制代码


除此之外还通过 @property 定义了 2 个变量,控制旋转的角度及小圆之间的间距。


通过 @property 声明的变量可以定义其语法、继承性和初始值。这样做的好处是可以在文档中明确地声明变量,并指定其用途和限制条件。这种声明方式更适合需要详细定义的场景,例如自定义属性。


@property --a {  syntax: "<angle>";  initial-value: 0deg;  inherits: true;}@property --i {  syntax: "<length>";  initial-value: 0px;  inherits: true;}
复制代码

背景绘制

背景图形上有多个小圆组成,小圆的数量是可配置的,所以背景的小圆需要基于所配置的数量动态生成,这里需要用到几个Sass的函数。


由于小圆的数量$n支持配置,所以整个元素的大小会随之影响发生变化。通过设置aspect-ratio,我们只需要控制width的变化即可。宽度的最终值基于小圆的半径和小圆的数量计算得出。


width: calc(var(--r)*(1 + 1/tan(180deg/#{$n})));aspect-ratio: 1;border-radius: 50%;
复制代码


接下来开始绘制附属在大圆上面的小圆。


$m: ();@for $i from 1 through ($n) {  $m: append($m,        radial-gradient(var(--c) 70%,#0000 72%) no-repeat        calc(50% + (50% - var(--i,0px))*cos(360deg*#{$i/$n} + var(--a,0deg)))         calc(50% + (50% - var(--i,0px))*sin(360deg*#{$i/$n} + var(--a,0deg)))/        var(--r) var(--r),       comma); }
复制代码


首先,我们定义一个变量 $m,并将其初始化为空。然后使用 @for 循环从 1 到 $n 小圆的数量进行遍历。


在循环内部,使用 Sassappend() 函数将新生成的 radial-gradient 样式追加到 $m 变量中。append() 函数用于在列表类型的变量后面添加一个新的元素,并返回新的列表。


radial-gradient 样式由以下几部分组成:


  • var(--c) 70%:表示渐变的颜色和渐变的位置,其中颜色使用 CSS 变量 --c

  • #0000 72%:表示渐变的结束颜色和结束位置。

  • no-repeat:表示不重复渐变。

  • calc(50% + (50% - var(--i,0px))*cos(360deg*#{$i/$n} + var(--a,0deg)))calc(50% + (50% - var(--i,0px))*sin(360deg*#{$i/$n} + var(--a,0deg))):计算渐变的圆心位置,其中变量 --i--a是自定义变量,默认值分别为 0px0deg

  • / var(--r) var(--r):表示渐变的尺寸,其中尺寸使用 CSS 变量 --r

  • comma:表示多个背景图像之间使用逗号分隔。


循环结束后,变量 $m 将包含所有生成的 radial-gradient 样式,可以在后续的样式中使用 $m 来应用这些背景图像。


基于上面的代码继续完善,将最终生成的图形绘制到背景中。


--_m:   radial-gradient(var(--c) calc(72% - var(--r)/2 - var(--i,0px)),#0000 0),  #{$m};-webkit-mask:   linear-gradient(#000 0 0) top/100% 50% no-repeat,  var(--_m);background: var(--_m);
复制代码


在上面的代码中,定义了一个新的 CSS 变量 --_m。它的值由两部分组成:


  1. 一个 radial-gradient 背景图像样式,其中渐变的颜色和位置使用 var(--c)calc(72% - var(--r)/2 - var(--i,0px)) 表示,这个渐变的结束颜色是 #0000,结束位置是 0。这部分内容就是整个背景的中心大圆部分。

  2. 以插值的方式引用之前定义的变量 $m


接着使用 -webkit-mask 属性为元素设置背景遮罩效果。它包含两部分:


  1. 一个线性渐变 linear-gradient,表示从顶部开始的黑色渐变。其中渐变的颜色为 #000,渐变的起始位置、结束位置分别为 00。设置了 top/100% 50% 表示 linear-gradient 的尺寸是水平方向占满整个宽度,垂直方向占高度的一半。no-repeat 表示不重复渐变。

  2. 引用之前定义的变量 --_m,将其作为元素的遮罩图像。


最后使用 background 属性将之前定义的变量 --_m 作为元素的背景图像。这样整个元素的背景就会显示之前生成的 radial-gradient 多个小圆的样式。


动画绘制

元素hover后动画细节拆分:


  • 背景圆旋转动画运行速度加快

  • 大圆附属小圆放大配置比例

  • 中心人物放大


hover前后动画速度不一样是两段不同执行时间的动画在切换,默认设置的动画如下:


--_a: rotate linear infinite;animation:   var(--_a) 10s,  var(--_a) 16s reverse;
@keyframes rotate { to{--a:360deg}}
复制代码


hover时将第一段动画设置running,第二段动画设置paused


animation-play-state: running, paused;
复制代码


上面绘制小圆的时候是基于--r半径绘制,我们还定义了--f控制hover时小圆放大比例的基数。--i在绘制小圆的时候设置了默认值是0pxhover时基于设定的变量进行计算赋值到--i,即可对校园进行放大的动画控制。


--i: calc(var(--r)/var(--f));
复制代码


对中心人物图像的放大使用如下代码,核心使用了小圆数量 $n,小圆半径--r进行计算最终放大的比例。


scale: calc((1 + 1/tan(180deg/#{$n}))/(1 - 2/var(--f) + 1/tan(180deg/#{$n})));
复制代码


另外还对主要的动画增加了过渡的效果,针对--iscale的切换增加0.4s的过渡时间,使动画更加丝滑。


transition: --i .4s, scale .4s;
复制代码

在线源码

https://code.juejin.cn/pen/7269700151160078348

最后

到此整体核心实现的逻辑就结束了,整个实现过程用到了不少Sass函数以及 CSS3 相关能力,定义了部分配置项使整个代码更加灵活可控,简洁高效。有兴趣的可以自己尝试看看。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~


专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

参考

A Fancy Hover Effect For Your Avatar II: css-tip.com/avatar-hover-effect-2/

发布于: 刚刚阅读数: 4
用户头像

南城FE

关注

还未添加个人签名 2019-02-12 加入

专注前端开发,分享前端知识

评论

发布
暂无评论
一个炫酷的头像悬停效果 2_CSS_南城FE_InfoQ写作社区