CSS mask 实现鼠标跟随镂空效果,阿里面试官必问

}`

效果如下:

a12d6122f9beee7eb709522858d77cdb.gif

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

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

五、CSS MASK 实现镂空


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

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

b3f08991f172b551dd944f9e06eb3235.png

用代码实现就是

.wrap::before{

content: ‘’;

position: absolute;

width: 100%;

height: 100%;

left: 0;

top: 0;

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

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

backdrop-filter: blur(5px)

}

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

d519ff0c41f59e6351fdb0204a9ccc77.gif

完整代码可以查看: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支持):

/* Keyword values */

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

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

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

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

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

2ea333553a1f9e4f892afbb45facba9b.png

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

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

-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; /只显示不重合的地方/

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

86a7053be884f2107b354ca242d0474e.png

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

.wrap::before{

content: ‘’;

position: absolute;

width: 100%;

height: 100%;

left: 0;

top: 0;

-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);

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

-webkit-mask-repeat: no-repeat;

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

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

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

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

backdrop-filter: blur(5px)

}

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

79a47affd5ddeb372bc648300c4efb34.gif

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

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

2d1a2e7c0a866ad2c353fc941c5a1570.png

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

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

3e1dfecb53dbe16d60a1bc7dfa9fa433.png

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

.wrap::before{

content: ‘’;

position: absolute;

width: 100%;

height: 100%;

left: 0;

top: 0;

-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);

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

-webkit-mask-repeat: no-repeat;

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

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

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

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

backdrop-filter: blur(5px)

}

星星镂空实现效果如下:

d3d415d2c47efd6fc354454c9751414a.gif

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

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

2e68df8b0aac7be0f2caa4082be22758.gif

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

只有想不到,没有做不到


七、总结和说明


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

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

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

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

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

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

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

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

作者:XboxYan

https://segmentfault.com/a/1190000040996523

推荐链接

  1. 纯 CSS 自定义多行省略:从原理到实现

  2. 前端程序员简历模板整理和下载

  3. 这才是前端该写的代码:CSS常见套路续

关注公众号 前端开发博客,回复“加群”,秒进群

加入我们一起学习,天天进步

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

最后

除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)**
[外链图片转存中…(img-ghVIgfon-1711732721729)]

最后

除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现摄像头跟随鼠标移动的效果,可以使用CSS的`transform`属性和JavaScript的`mousemove`事件来实现。 首先,在HTML中创建一个包含摄像头的容器元素,例如: ```html <div class="camera-container"> <video id="camera"></video> </div> ``` 然后,在CSS中设置容器元素的宽度和高度,以及摄像头的位置,例如: ```css .camera-container { position: relative; width: 640px; height: 480px; } #camera { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform: translate(-50%, -50%); } ``` 这里的关键是将摄像头的位置设置为绝对定位,并使用`transform: translate(-50%, -50%);`将其居中对齐。 接下来,在JavaScript中监听`mousemove`事件,并计算出鼠标相对于容器元素的位置,然后使用`transform: translate()`将摄像头移动到相应的位置。代码如下: ```javascript var cameraContainer = document.querySelector('.camera-container'); var camera = document.querySelector('#camera'); cameraContainer.addEventListener('mousemove', function(event) { var x = event.clientX / cameraContainer.offsetWidth; var y = event.clientY / cameraContainer.offsetHeight; camera.style.transform = 'translate(' + (x * 50 - 25) + '%, ' + (y * 50 - 25) + '%)'; }); ``` 这里使用`event.clientX`和`event.clientY`获取鼠标的坐标,然后将其除以容器元素的宽度和高度,得到相对于容器元素的位置比例。最后使用`transform: translate()`将摄像头移动到相应的位置。 完整的代码示例可以参考下面的代码片段: ``` .camera-container { position: relative; width: 640px; height: 480px; } #camera { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform: translate(-50%, -50%); } ``` ``` <div class="camera-container"> <video id="camera" autoplay></video> </div> <script> var cameraContainer = document.querySelector('.camera-container'); var camera = document.querySelector('#camera'); cameraContainer.addEventListener('mousemove', function(event) { var x = event.clientX / cameraContainer.offsetWidth; var y = event.clientY / cameraContainer.offsetHeight; camera.style.transform = 'translate(' + (x * 50 - 25) + '%, ' + (y * 50 - 25) + '%)'; }); navigator.mediaDevices.getUserMedia({ video: true }) .then(function(stream) { camera.srcObject = stream; }) .catch(function(error) { console.error(error); }); </script> ``` 注意,这里还使用了`navigator.mediaDevices.getUserMedia()`获取摄像头的视频流,并将其赋值给`<video>`元素的`srcObject`属性,以便显示摄像头的内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值