原文地址:CSS mask 实现鼠标跟随镂空效果_前端开发博客的博客-CSDN博客

点击下方星标公众号,实用前端技术文章及时了解

偶然在某思看到这样一个问题,如何使一个div的部分区域变透明而其他部分模糊掉?,最后实现效果是这样的:

进一步,还能实现任意形状的镂空效果:

鼠标经过的地方清晰可见,其他地方则是模糊的。

可能一开始无从下手,不要急,可以先从简单的、类似的效果开始,一步一步尝试,一起看看吧。

一、普通半透明的效果

比如平时开发中碰到更多的可能是一个半透明的效果,有点类似于探照灯(鼠标外面的地方是半透明遮罩,看起来会暗一点)。如下:

那先从这种效果开始吧,假设有这样一个布局:

  1. <div class="wrap" id="img">

  2.     <img class="prew" src="https://tva1.sinaimg.cn/large/008i3skNgy1gubr2sbyqdj60xa0m6tey02.jpg">

  3. </div>

那么如何绘制一个镂空的圆呢?先介绍一种方法。

其实很简单,只需要一个足够大的投影就可以了,原理如下:

这里可以用伪元素::before来绘制,结构更加精简。用代码实现就是:

  1. .wrap::before{

  2.   content:'';

  3.   position: absolute;

  4.   width: 100px;

  5.   height: 100px;

  6.   border-radius: 50%;

  7.   left: 50%;

  8.   top: 50%;

  9.   transform: translate(-50%,-50%); /*默认居中*/

  10.   box-shadow: 0 0 0 999vw rgba(0, 0, 0, .5); /*足够大的投影*/

  11. }

可以得到这样的效果:

二、借助 CSS 变量传递鼠标位置

按照以往的经验,可能会在 js 中直接修改元素的 style 属性,类似这样

  1. img.addEventListener('mousemove', (ev) => {

  2.     img.style.left = '...';

  3.     img.style.top = '...';

  4. })

但是这样交互与业务逻辑混杂在一起,不利于后期维护。其实,我们只需要鼠标的坐标,在 CSS 中也能完全实现跟随的效果。

这里借助 CSS 变量,那一切就好办了!假设鼠标的坐标是 [--x,--y](范围是[0, 1]),那么遮罩的坐标就可以使用 calc计算了。

  1. .wrap::before{

  2.   left: calc(var(--x) * 100%);

  3.   top: calc(var(--y) * 100%);

  4. }

然后鼠标坐标的获取可以使用 JS 来计算,也比较容易,如下:

  1. img.addEventListener('mousemove', (ev) => {

  2.     img.style.setProperty('--x', ev.offsetX / ev.target.offsetWidth);

  3.     img.style.setProperty('--y', ev.offsetY / ev.target.offsetHeight);

  4. })

这样,半透明效果的镂空效果就完成了。

完整代码可以访问:https://codepen.io/xboxyan/pen/VwzRaNZ

三、渐变也能实现半透明的效果

除了上述阴影扩展的方式,CSS 径向渐变也能实现这样的效果。

绘制一个从透明到半透明的渐变,如下:

  1. .wrap::before{

  2.     content: '';

  3.     position: absolute;

  4.     width: 100%;

  5.     height: 100%;

  6.     left: 0;

  7.     top: 0;

  8.     background: radial-gradient( circle at center, transparent 50px, rgba(0,0,0,.5) 51px);

  9. }

可以得到这样的效果:

然后,把鼠标坐标映射上去就可以了。从这里就可以看出 CSS 变量的好处,无需修改 JS,只需要在CSS中修改渐变中心点的位置就可以实现了

  1. .wrap::before{

  2.   background: radial-gradient( circle at calc(var(--x) * 100% )  calc(var(--y) * 100% ), transparent 50px, rgba(0,0,0,.5) 51px);

  3. }

四、背景模糊的效果尝试

CSS 中有一个专门针对背景(元素后面区域)的属性:backdrop-filter。

backdrop-filter链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter

使用方式和 filter完全一致!

backdrop-filter: blur(10px);

下面是 MDN 中的一个示意效果:

backdrop-filter是让当前元素所在区域后面的内容模糊,要想看到效果,需要元素本身半透明或者完全透明;而filter是让当前元素自身模糊。

有兴趣的可以查看这篇文章:CSS backdrop-filter简介与苹果iOS毛玻璃效果 « 张鑫旭-鑫空间-鑫生活 (zhangxinxu.com)

文章链接:https://www.zhangxinxu.com/wordpress/2019/11/css-backdrop-filter/

需要注意的是,这种模糊与背景的半透明度没有任何关系,哪怕元素本身是透明的,仍然会有效果。例如下面是去除背景后的效果 ,整块都是模糊的。

如果直接运用到上面的例子会怎么样呢?

1. 阴影实现

在上面第一个例子中添加 backdrop-filter

  1. .wrap::before{

  2.   content:'';

  3.   position: absolute;

  4.   width: 100px;

  5.   height: 100px;

  6.   border-radius: 50%;

  7.   left: 50%;

  8.   top: 50%;

  9.   transform: translate(-50%,-50%); /*默认居中*/

  10.   box-shadow: 0 0 0 999vw rgba(0, 0, 0, .5); /*足够大的投影*/

  11.   backdrop-filter: blur(5px)

  12. }

得到效果如下:

可以看到圆形区域是模糊的,正好和希望的效果相反。其实也好理解,只有圆形区域才是真实的结构,外面都是阴影,所以最后作用的范围也只有圆形部分。

2. 渐变实现

现在在第二个例子中添加 backdrop-filter

  1. .wrap::before{

  2.     content: '';

  3.     position: absolute;

  4.     width: 100%;

  5.     height: 100%;

  6.     left: 0;

  7.     top: 0;

  8.     background: radial-gradient( circle at calc(var(--x) * 100% )  calc(var(--y) * 100% ), transparent 50px, rgba(0,0,0,.5) 51px);

  9.       backdrop-filter: blur(5px)

  10. }`

效果如下:

已经全部都模糊了,只是圆形区域外暗一些。由于::before的尺寸占据整个容器,所以整个背后都变模糊了,圆形外部比较暗是因为半透明渐变的影响。

总之还是不能满足我们的需求,需要寻求新的解决方式。

五、CSS MASK 实现镂空

与其说是让圆形区域不模糊,还不如说是把那块区域给镂空了。就好比之前是一整块磨砂玻璃,然后通过 CSS MASK 打了一个圆孔,这样透过圆孔看到后面肯定是清晰的。

可以对第二个例子稍作修改,通过径向渐变绘制一个透明圆,剩余部分都是纯色的遮罩层,示意如下:

用代码实现就是

  1. .wrap::before{

  2.     content: '';

  3.     position: absolute;

  4.     width: 100%;

  5.     height: 100%;

  6.     left: 0;

  7.     top: 0;

  8.     -webkit-mask: radial-gradient( circle at calc(var(--x, .5) * 100% )  calc(var(--y, .5) * 100% ), transparent 50px, #000 51px);

  9.       background: rgba(0,0,0,.3);

  10.       backdrop-filter: blur(5px)

  11. }

这样就实现了文章开头的效果:

完整代码可以查看:https://codepen.io/xboxyan/pen/porpoXJ

六、CSS MASK COMPOSITE 实现更丰富的镂空效果

除了使用径向渐变绘制遮罩层以外,还可以通过 CSS MASK COMPOSITE(遮罩合成)的方式来实现。

CSS MASK COMPOSITE 链接:https://developer.mozilla.org/en-US/docs/Web/CSS/mask-composite

标准关键值如下(firefox支持):

  1. /* Keyword values */

  2. mask-composite: add; /* 叠加(默认) */

  3. mask-composite: subtract; /* 减去,排除掉上层的区域 */

  4. mask-composite: intersect; /* 相交,只显示重合的地方 */

  5. mask-composite: exclude; /* 排除,只显示不重合的地方 */

遮罩合成是什么意思呢?可以类比 photoshop 中的形状合成,几乎是一一对应的。

-webkit-mask-composite 与标准下的值有所不同,属性值非常多,如下(chorme 、safari 支持)

-webkit-mask-composite 链接:https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-composite

  1. -webkit-mask-composite: clear; /*清除,不显示任何遮罩*/

  2. -webkit-mask-composite: copy; /*只显示上方遮罩,不显示下方遮罩*/

  3. -webkit-mask-composite: source-over; 

  4. -webkit-mask-composite: source-in; /*只显示重合的地方*/

  5. -webkit-mask-composite: source-out; /*只显示上方遮罩,重合的地方不显示*/

  6. -webkit-mask-composite: source-atop;

  7. -webkit-mask-composite: destination-over;

  8. -webkit-mask-composite: destination-in; /*只显示重合的地方*/

  9. -webkit-mask-composite: destination-out;/*只显示下方遮罩,重合的地方不显示*/

  10. -webkit-mask-composite: destination-atop;

  11. -webkit-mask-composite: xor; /*只显示不重合的地方*/

是不是一脸懵?这里做了一个对应的效果图,如果不太熟练,使用的时候知道有这样一个功能,然后对着找就行了。

回到这里,可以绘制一整块背景和一个圆形背景,然后通过遮罩合成排除(mask-composite: exclude)打一个孔就行了,实现如下:

  1. .wrap::before{

  2.     content: '';

  3.     position: absolute;

  4.     width: 100%;

  5.     height: 100%;

  6.     left: 0;

  7.     top: 0;

  8.     -webkit-mask: url("data:image/svg+xml,%3Csvg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg"%3E%3Ccircle cx="25" cy="25" r="25" fill="%23C4C4C4"/%3E%3C/svg%3E"), linear-gradient(red, red);

  9.       -webkit-mask-size: 50px, 100%;

  10.       -webkit-mask-repeat: no-repeat;

  11.       -webkit-mask-position: calc(var(--x, .5) * 100% + var(--x, .5) * 100px - 50px )  calc(var(--y, .5) * 100% + var(--y, .5) * 100px - 50px ), 0;

  12.       -webkit-mask-composite: xor;   /*只显示不重合的地方, chorem 、safari 支持*/

  13.       mask-composite: exclude; /* 排除,只显示不重合的地方, firefox 支持 */

  14.       background: rgba(0,0,0,.3);

  15.       backdrop-filter: blur(5px)

  16. }

需要注意-webkit-mask-position中的计算,这样也能很好的实现这个效果:

完整代码可以查看:https://codepen.io/xboxyan/pen/ExvMpQB

你可能已经发现,上述例子中的圆是通过 svg 绘制的,还用到了遮罩合成,看着好像更加繁琐了。其实呢,这是一种更加万能的解决方式,可以带来无限的可能性。比如我需要一个星星⭐️的镂空效果,很简单,先通过一个绘制软件画一个。

然后把这段 svg 代码转义一下,这里推荐使用张鑫旭老师的SVG在线压缩合并工具。

链接:https://www.zhangxinxu.com/sp/svgo/

替换到刚才的例子中就可以了。

  1. .wrap::before{

  2.     content: '';

  3.     position: absolute;

  4.     width: 100%;

  5.     height: 100%;

  6.     left: 0;

  7.     top: 0;

  8.     -webkit-mask: url("data:image/svg+xml,%3Csvg width="96" height="91" viewBox="0 0 96 91" fill="none" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M48 0l11.226 34.55h36.327l-29.39 21.352L77.39 90.45 48 69.098 18.61 90.451 29.837 55.9.447 34.55h36.327L48 0z" fill="%23C4C4C4"/%3E%3C/svg%3E"), linear-gradient(red, red);

  9.       -webkit-mask-size: 50px, 100%;

  10.       -webkit-mask-repeat: no-repeat;

  11.       -webkit-mask-position: calc(var(--x, .5) * 100% + var(--x, .5) * 100px - 50px )  calc(var(--y, .5) * 100% + var(--y, .5) * 100px - 50px ), 0;

  12.       -webkit-mask-composite: xor;   /*只显示不重合的地方, chorem 、safari 支持*/

  13.       mask-composite: exclude; /* 排除,只显示不重合的地方, firefox 支持 */

  14.       background: rgba(0,0,0,.3);

  15.       backdrop-filter: blur(5px)

  16. }

星星镂空实现效果如下:

完整代码可以查看:https://codepen.io/xboxyan/pen/vYJPaVy

再比如一个心形❤,实现效果如下:

完整代码可以查看:https://codepen.io/xboxyan/pen/KKvEBjb

只有想不到,没有做不到

七、总结和说明

以上实现了一个鼠标跟随镂空的效果,从简单到复杂,从单一到通用,虽然借助了一点点 JS ,但是仅仅是“工具人”的角色,交互逻辑全部都由 CSS 完成,下面总结一下:

  1. 足够大的阴影是一个实现圆形镂空效果的小技巧

  2. CSS 渐变也能轻易的绘制出圆形镂空背景

  3. 借助 CSS 变量可以很方便的利用鼠标位置实现想要的效果

  4. backdrop-filter 可以想象成磨砂玻璃的功能

  5. CSS Mask 可以给磨砂玻璃打孔,实现镂空的效果

  6. 借助遮罩合成特性和SVG,可以实现任意形状的镂空效果

CSS MASK 还是非常强大的,有必要还是多掌握一下。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、在看、收藏、转发。

图片半透明圆形镂空遮罩相关推荐

  1. html 将图片镂空,遮罩层镂空效果的多种实现方法

    先看看效果 [ 方法一:截图模拟实现 ] 原理:先截一张相同位置的图片,创建一个遮罩层,然后把图片定位在相应的位置上. 优点:原理简单:兼容性好,可以兼容到IE6.IE7:可以同时实现镂空多个. 缺点 ...

  2. Android自定义相机镂空遮罩

    前言 最近在做项目时需要自定义相机拍照,并在预览页面显示一个取景框,效果如图: 本文只讲镂空遮罩的实现,照相部分不做解释. 思路 考虑到需要获取取景框的坐标信息进行裁剪,所以用自定义View实现. 实 ...

  3. 镂空遮罩(新手指引解决方案)

    1.使用svg的方式,画个圆 网上示例(遮罩图层) .container {position: relative;.svg {position: absolute;}.rect1 {stroke:no ...

  4. Android Glide加载图片成圆形

    今天,简单讲解android使用glide加载图片成圆形. 这个很简单,因为之前需要在RecyclerView里加载圆形图片,所以在网上查找了资料,很简单就解决了. 1.导入依赖 implementa ...

  5. jQuery hover事件鼠标滑过图片半透明标题文字滑动显示隐藏

    1.效果及功能说明 hover事件制作产品图片鼠标滑过图片半透明,标题文字从左到右滑动动画移动显示隐藏 2.实现原理 首先把效果都隐藏,然后定义一个伪类来触发所有的效果,接下来当触发伪类后会有一个遍历 ...

  6. Python 将矩形图片转为圆形图片

    使用PIL库将矩形图片转为原型图片 from PIL import Image, ImageDraw, ImageFilterdef crop_max_square(pil_img):return c ...

  7. Bootstrap4 图片形状——圆形实现

    Bootstrap4 图片形状--圆形实现 突然用到了Bootstrap4,要实现一个card里面的用户头像,需要正圆,但是看了文档,只有 .rounded实现图片的圆角,我尝试加入border-ra ...

  8. android glide圆形图片,Android Glide加载图片成圆形

    释放双眼,带上耳机,听听看~! 今天,简单讲解android使用glide加载图片成圆形. 这个很简单,因为之前需要在RecyclerView里加载圆形图片,所以在网上查找了资料,很简单就解决了. 1 ...

  9. css只设置背景图片半透明,css3实现背景图片半透明内容不透明的方法示例

    上一个博客做登陆的页面是遇到的问题,突然想使用这种背景图片透明,而内容不透明的效果,这里我就说一说我的两个思路吧. 效果展示: 内容半透明 内容不透明 最常见的做法事设置元素的opacity,这种设置 ...

最新文章

  1. 交通信号灯检测与行人过马路策略
  2. 【Linux】Linux简单操作之文件管理
  3. 如何获取并操作listview中的控件
  4. ESP32 OTA 接口简略说明
  5. 完全卸载mysql数据库图文教程
  6. MDL锁导致mysql夯住_MySQL MetaData Lock 案例分享
  7. autoresizingMask的用法
  8. 远程预付费电能管理系统在工业园的应用,主要功能有哪些?
  9. android 远程组件,安卓手机远程协助控制神器 Teamviewer
  10. 深入理解正向代理和反向代理
  11. MATLAB画图符号标注
  12. 微信H5音乐自动播放
  13. js 树状图数组批量循环操作
  14. 第八十四章 Caché 函数大全 $ZDATEH 函数
  15. 可爱猫咪,用 CSS 告诉你为何大橘为重!!
  16. tableau绘制雷达图(4步法)
  17. 基于Dragonboard410c的智能音箱(四)
  18. VulnStack-ATTCK-3(红日靶场三)
  19. 因签署Android独家协议排除竞争对手 谷歌在印度被罚款1.62亿美元
  20. WebGL简易教程(十四):阴影

热门文章

  1. Python 数据处理数据挖掘(四):用户分层模型RFM
  2. laravel获取器和修改器
  3. 图说TechCrunch Disrupt NY 很艺术很幽默
  4. UG模具设计之注塑模具设计的原则及要求
  5. java编程如何算圆的面具,Java实现人物拼图游戏│附代码
  6. 手机删除密码文件暴力解锁
  7. 浅谈亚马逊测评,及四大测评干货!
  8. One Day One Step 之Dual Palindromes
  9. Android关于包体不符合谷歌play关于提供64位版本应用的规定
  10. 信号处理之卷积神经网络结构