一个有意思的CSS图片Hover效果

开发 前端
提到切割,可以想到镂空,进而可以想到遮罩(CSS Mask)。关于遮罩,这个技巧非常实用。

今天来分享一个比较有意思的图片 hover 效果,如下:

图片

案例来源于https://codepen.io/t_afif/details/abRWELR[1],略有修改。

仔细观察,这个效果主要有两个要点。

  1. 图片被切割成多个矩形。
  2. 每个矩形会旋转 90 度。

那么,这个是如何实现的呢?花几分钟时间一起看看吧。

一、分割的矩形

假设HTML是这样的,很简单,就一个图片。

<img src="xxx.jpg" alt="xxx">

然后,我们需要一个变量,来控制分割的数量,比如2表示2*2,这里可以用 CSS 变量。

img{
  --n: 4; /*横纵分割的数量*/
}

那么,如何来切割呢?

提到切割,可以想到镂空,进而可以想到遮罩(CSS Mask)。关于遮罩,这个技巧非常实用,之前在多篇文章中都有用到

  • CSS 如何实现羽化效果?[2]
  • 别用图片了,CSS 遮罩合成实现带圆角的环形 loading 动画[3]
  • CSS mask 实现鼠标跟随镂空效果[4]
  • CSS 实现Chrome标签栏的技巧[5]
  • CSS 实现优惠券的技巧[6]

原理很简单,最终效果只显示不透明的部分,透明部分将不可见,半透明类推,例如:

图片

在这里,我们可以通过类似背景平铺的方式,来将一个完整的图片切割成n*n个矩形,如下:

img{
  --n: 4;
  -webkit-mask: radial-gradient(black, transparent);
  -webkit-mask-size: calc(100% / var(--n)) calc(100% / var(--n));
}

这里用了一个径向渐变做了遮罩图片,遮罩尺寸是100% / var(--n),刚好将完整的图片分成了n*n份,效果如下,分别是2*2和4*4的效果。

图片

这就是分割的原理了。

二、旋转的矩形

那么,问题来了,这里是背景层,并没有rotate这样的属性,如何让一个矩形旋转呢?或者说,如何绘制一个倾斜的矩形呢?

下面就来一步一步实现。

由于遮罩和背景的语法基本一致,为了方便调试,可以先用背景代替。

大家都知道,线性渐变是可以设置角度的,为了计算方便,我们可以用 CSS 变量来表示。

div{
  --r: 45deg;
  background: linear-gradient(var(--r), red, orange)
}

这样可以得到一个45deg的渐变。

图片

然后,我们可以将这个渐变改成透明→纯色→透明的渐变。

div{
  --r: 45deg;
  background: linear-gradient(var(--r), transparent 5%, orange 0 95%, transparent 0)
}

效果如下:

图片

为了计算方便,可以将透明的比例用 CSS 变量来表示。

div{
  --r: 45deg;
  --d: 30%;
  background: linear-gradient(var(--r), transparent var(--d), orange 0 calc(100% - var(--d)), transparent 0)
}

下面是30%的效果。

图片

接下来,用同样的方式绘制和这个垂直的图形,也就是角度相差90deg。

div{
  --r: 45deg;
  --d: 30%;
  background: linear-gradient(var(--r), transparent var(--d), orange 0 calc(100% - var(--d)), transparent 0),
    linear-gradient(calc(var(--r) + 90deg), transparent var(--d), red 0 calc(100% - var(--d)), transparent 0),
}

效果如下:

图片

注意观察,两个重叠的部分不就是一个旋转45deg的矩形吗?如下:

图片

可以任意改变角度。

div{
  --deg: 15deg
}

图片

下面改变背景尺寸,变成4*4的效果:

div{
  background-size: 50% 50%
}

图片

是不是和我们想要的效果有点相似呢?下面将背景用做遮罩。

img{
  --r: 30deg;
  --d: 30%;
  -webkit-mask:
    linear-gradient(var(--r), transparent var(--d),red 0 calc(100% - var(--d)), transparent 0),
    linear-gradient(calc(var(--r) + 90deg), transparent var(--d), red 0 calc(100% - var(--d)), transparent 0);
  -webkit-mask-size: calc(100%/var(--n)) calc(100%/var(--n));
}

变成了这样。

图片

是不是很凌乱?这是因为现在的遮罩还是直接叠加的,并不是只显示重叠部分,可以设置遮罩合成mask-composite,也就是将图形进行布尔运算,得出我们想要的图形,这里简单介绍一下。

mask-composite - CSS: Cascading Style Sheets | MDN (mozilla.org)[7]

/* Keyword values */
mask-composite: add; /* 叠加(默认) */
mask-composite: subtract; /* 减去,排除掉上层的区域 */
mask-composite: intersect; /* 相交,只显示重合的地方 */
mask-composite: exclude; /* 排除,只显示不重合的地方 */

相信在很多图形设计软件中都见到类似的操作(下面是 photoshop)。

图片

这些是标准属性,Chrome 还不支持,可以用带前缀的属性-webkit-mask-composite[8] ,但是值和上面这些不同,非常多,主要有这些。

-webkit-mask-composite: clear; /*清除,不显示任何遮罩*/
-webkit-mask-composite: copy; /*只显示上方遮罩,不显示下方遮罩*/
-webkit-mask-composite: source-over; /*叠加,两者都显示*/
-webkit-mask-composite: source-in; /*只显示重合的地方*/
-webkit-mask-composite: source-out; /*只显示上方遮罩,重合的地方不显示*/
-webkit-mask-composite: source-atop;
-webkit-mask-composite: destination-over; /*叠加,两者都显示*/
-webkit-mask-composite: destination-in; /*只显示重合的地方*/
-webkit-mask-composite: destination-out;/*只显示下方遮罩,重合的地方不显示*/
-webkit-mask-composite: destination-atop;
-webkit-mask-composite: xor; /*只显示不重合的地方*/

回到这里,我们想要得到两者重叠的部分,所以可以。

-webkit-mask-composite: source-in;

效果如下:

图片

三、动画

最后就是动画了。

我们需要在hover的时候,将矩形旋转90deg,可以直接改变--r这个变量。

img{
  --r: 0deg;
}
img:hover{
  --r: 90deg;
  transition: 0.5s;
}

但是,仅仅这样是没有动画的,因为--r并不是一个合法的、可以过渡的属性。

图片

这时可以用到 CSS @property[9]。可以让任意变量像颜色一样进行支持过渡和动画

@property --r {
   syntax: "<angle>";
   initial-value: 0deg;
   inherits: false;
}

现在就有过渡效果了。

图片

现在还有一个问题,空隙太大了,还需要改变--d的大小,起始点应该是0%,在中间45deg时最大,也就是0%→20%→0%,可以用animation实现。

@keyframes d {
  0%,100%{
    --d: 0%
  }
  50%{
    --d: 20%
  }
}
img:hover{
  --r: 90deg;
  transition: 0.5s;
  animation: d .5s;
}

效果如下:

图片

当然还可以将这个过渡和动画写在一个动画里。

@keyframes r {
  0%{
    --d: 0%
  }
  100%{
    --d: 0%;
    --r: 90deg
  }
  50%{
    --d: 20%
  }
}
img:hover{
  animation: r .5s;
}

这样也能实现相同的效果,下面分别是2*2、4*4、6*6的效果。

<img src="xxx.jpg" alt="xxx" style="--n:2">
<img src="xxx.jpg" alt="xxx" style="--n:4">
<img src="xxx.jpg" alt="xxx" style="--n:6">

图片

完整代码可以查看以下任意链接:

  • CSS img hover (juejin.cn)[10]
  • CSS img hover (runjs.work)[11]
  • CSS img hover (codepen.io)[12]

四、总结和说明

以上就是实现的全部过程了,代码其实不多,其实主要难点在于旋转矩形的绘制,整体实现其实并不困难,难点其实是创意,可惜的是平时接触的还是太少😥。下面总结一下实现要点:

  1. 提到切割,可以想到镂空,进而可以想到遮罩。
  2. 分割成n*n块,其实就是遮罩背景的平铺。
  3. 旋转的矩形其实就是两个互相垂直的线性渐变重叠而成。
  4. CSS 变量的过渡动画需要用到CSS @property 特性。

兼容性其实就取决于CSS @property了,这是CSS Houdini的一部分,目前只有 Chrome 和 Safari支持。

图片

参考资料

[1]https://codepen.io/t_afif/details/abRWELR: https://codepen.io/t_afif/details/abRWELR。

[2]CSS 如何实现羽化效果?: https://juejin.cn/post/7176094306124431421。

[3]别用图片了,CSS 遮罩合成实现带圆角的环形 loading 动画: https://juejin.cn/post/7217731969307328571。

[4]CSS mask 实现鼠标跟随镂空效果: https://juejin.cn/post/7033188994641100831。

[5]CSS 实现Chrome标签栏的技巧: https://juejin.cn/post/6986827061461516324。

[6]CSS 实现优惠券的技巧 : https://juejin.cn/post/6945023989555134494。

[7]mask-composite - CSS: Cascading Style Sheets | MDN (mozilla.org): https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FCSS%2Fmask-composite。

[8]-webkit-mask-composite: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FCSS%2F-webkit-mask-composite。

[9]CSS @property: https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property。

[10]CSS img hover (juejin.cn): https://code.juejin.cn/pen/7232884497778704440。

[11]CSS img hover (runjs.work): https://runjs.work/projects/a1f43973537d4e05。

[12]CSS img hover (codepen.io): https://codepen.io/xboxyan/pen/vYVaNNp。

责任编辑:姜华 来源: 前端侦探
相关推荐

2020-12-12 13:50:16

云开发

2021-01-27 13:54:05

开发云原生工具

2018-06-24 16:39:28

Tomcat异常线程

2009-08-26 17:53:31

C# DropDown

2022-03-21 10:21:50

jQuery代码模式

2021-04-09 08:23:30

Css前端加载动画

2015-03-12 10:46:30

代码代码犯罪

2021-03-25 06:12:55

SVG 滤镜CSS

2012-06-15 10:33:06

JavaScript

2012-05-22 10:12:59

jQuery

2024-03-18 08:14:07

SpringDAOAppConfig

2021-06-10 08:15:49

CSS 文字动画技巧

2022-06-15 07:21:47

鼠标指针交互效果CSS

2021-02-20 16:01:26

Github前端开发

2022-08-15 22:34:47

Overflow方向裁切

2022-05-20 07:36:02

LiveTerm工具

2020-03-10 14:59:16

oracle数据库监听异常

2022-07-11 13:09:26

mmapLinux

2020-08-03 08:30:00

JSCSS排序

2017-08-01 00:52:07

kafka大数据消息总线
点赞
收藏

51CTO技术栈公众号