当前位置: 首页 > Web前端 > HTML

cssmask实现鼠标跟随的镂空效果

时间:2023-03-29 11:58:38 HTML

某思考无意中看到这样的问题,如何让一个div一部分透明,另一部分模糊?,最终的效果就是这样更进一步,而且还可以实现任意形状的镂空效果。鼠标经过的地方清晰可见,而其他地方则模糊不清。刚开始可能会比较吃力,别着急,你可以从一个简单的,类似的效果开始,一步步尝试,一起来看看吧。1.普通半透明效果。比如在平时的开发中,可能是半透明的效果,有点类似于探照灯(鼠标外面的区域是半透明的mask,看起来暗一点)。如下:我们先从这个效果开始,假设有这样一个布局:

那么空心圆怎么画呢?先介绍一个方法,其实很简单。你只需要一个足够大的投影。原理如下。这里可以使用伪元素::before来绘制,结构更加精简。代码实现为.wrap::before{content:'';位置:绝对;宽度:100px;高度:100px;边界半径:50%;左:50%;顶部:50%;转换:翻译(-50%,-50%);/*默认居中*/box-shadow:000999vwrgba(0,0,0,.5);/*足够大的投影*/}可以得到这个效果css变量传鼠标位置根据以往的经验,在js中可以直接修改元素的style属性,像这样img.addEventListener('mousemove',(ev)=>{img.style.left='...';img.style.top='...';})但是这样的交互和业务逻辑混在一起,不利于后期维护。其实我们只需要鼠标的坐标,下面的效果完全可以用CSS来实现。在这里有了CSS变量的帮助,一切都好办了!假设鼠标的坐标为[--x,--y](取值范围为[0,1]),那么使用calc就可以计算出mask的坐标。wrap::before{left:calc(var(--x)*100%);top:calc(var(--y)*100%);}然后可以用JS计算鼠标坐标,也比较容易,如下img.addEventListener('mousemove',(ev)=>{img.style.setProperty('--x',ev.offsetX/ev.target.offsetWidth);img.style.setProperty('--y',ev.offsetY/ev.target.offsetHeight);})这样,半透效果的镂空效果就完成了。完整代码可以访问:backdrop-shadow(codepen.io)3.渐变也可以实现半透明的效果除了上面提到的阴影延伸的方法,CSSradialgradients也可以实现这种效果绘制一个从透明到透明的渐变半透明,如下。包装::之前{内容:'';位置:绝对;宽度:100%;高度:100%;左:0;顶部:0;background:radial-gradient(circleatcenter,transparent50px,rgba(0,0,0,.5)51px);}你可以得到这个效果,然后只需将鼠标坐标映射到它。从这里可以看出CSS变量的好处,不用修改JS,只需要修改CSS中渐变中心点的位置即可。wrap::before{background:radial-gradient(circleatcalc(var(--x)*100%)calc(var(--y)*100%),transparent50px,rgba(0,0,0,.5)51px);}4.试试背景虚化的效果。背景属性(元素后面的区域):backdrop-filter。用法和filter完全一样!背景滤镜:模糊(10px);下面是MDN中的示意图效果。backdrop-filter是对当前元素所在区域后面的内容进行模糊处理。要看到效果,元素本身需要是半透明或完全透明的;而filter就是让当前元素本身变得模糊。有兴趣的可以看看这篇文章:CSSbackdrop-filter介绍和AppleiOS的毛玻璃效果元素本身是透明的,还是会有效果的。比如下面是去掉背景后的效果,整块都模糊了,如果直接套用在上面的例子上呢?1.阴影实现添加backdrop-filter.wrap::before{content:'';位置:绝对;宽度:100px;高度:100px;边界半径:50%;左:50%;在上面的第一个例子中:50%;转换:翻译(-50%,-50%);/*默认居中*/box-shadow:000999vwrgba(0,0,0,.5);/*足够大的投影*/backdrop-filter:blur(5px)}效果如下。可以看到圆形区域是模糊的,这与想要的效果正好相反。其实很容易理解,只有圆形区域才是真正的结构,外面覆盖了阴影,所以最终的作用范围只有圆形部分2.渐变实现现在添加backdrop-filter.wrap::在第二个例子之前{content:'';位置:绝对;宽度:100%;高度:100%;左:0;顶部:0;背景:径向渐变(圆圈在calc(var(--x)*100%)calc(var(--y)*100%),透明50px,rgba(0,0,0,.5)51px);backdrop-filter:blur(5px)}效果如下,全部都模糊了,只有圆形区域外面更暗。由于::before的大小占满了整个容器,所以整个背面都模糊了,圆圈外面因为半透明的渐变,颜色更深了。总之,还是不能满足我们的需求,需要寻找新的解决方案。5、CSSMASK的镂空与其说是让圆形区域不模糊,不如说是把那个区域镂空。就好像之前是一整块磨砂玻璃,然后通过CSSMASK打了一个圆孔,这样通过圆孔一定能看清背面。可以稍微修改一下第二个例子,通过径向渐变绘制一个透明圆圈,遮罩层的其余部分为纯色,如下代码实现所示为.wrap::before{content:'';位置:绝对;宽度:100%;高度:100%;左:0;顶部:0;-webkit-mask:radial-gradient(circleatcalc(var(--x,.5)*100%)calc(var(--y,.5)*100%),transparent50px,#00051px);背景:rgba(0,0,0,.3);backdrop-filter:blur(5px)}这样就完成了文章开头的效果代码可以查看:backdrop-mask(codepen.io)6.CSSMASKCOMPOSITE实现更丰富的镂空效果除了使用radial渐变来绘制遮罩层,也可以通过CSSMASKCOMPOSITE(遮罩合成)来实现。标准键值如下(firefox支持):/*Keywordvalues*/mask-composite:add;/*覆盖(默认)*/mask-composite:subtract;/*减去,排除上层区域*/mask-composite:intersect;/*相交,只显示重叠的地方*/mask-composite:exclude;/*exclude,只显示不重叠的地方*/maskcomposite是什么意思?可以类比photoshop中的形状合成,几乎一一对应-webkit-mask-composite与标准值不同,属性值较多,如下(chorme,safari支持)-webkit-mask-复合材料:清晰;/*清除,不显示任何遮罩*/-webkit-mask-composite:copy;/*只显示上掩码,不显示下掩码*/-webkit-mask-composite:source-over;-webkit-mask-composite:source-in;/*只显示重叠的地方*/-webkit-mask-composite:source-out;/*只显示上面的mask,重叠的地方不显示*/-webkit-mask-composite:source-atop;-webkit-mask-composite:destination-over;-webkit-mask-composite:destination-in;/*只显示重叠的地方*/-webkit-mask-composite:destination-out;/*只显示在Mask下方,重叠的地方不显示*/-webkit-mask-composite:destination-atop;-webkit-mask-composite:异或;/*只显示不重叠的地方*/你是不是一头雾水?下面是相应的效果图。如果不是很熟练,用了就知道有这么个功能,然后找找就行了。回到这里,可以绘制一个整体背景和一个圆形背景,然后通过maskExclude(mask-composite:exclude)合成它们就打个洞就行了,实现如下。包装::之前{内容:'';位置:绝对;宽度:100%;高度:100%;左:0;顶部:0;-webkit-mask:url("data:image/svg+xml,%3Csvgwidth='50'height='50'viewBox='005050'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Ccirclecx='25'cy='25'r='25'fill='%23C4C4C4'/%3E%3C/svg%3E"),线性渐变(红色,红色的);-webkit-mask-size:50px,100%;-webkit-mask-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中,这个也可以你可以查看完整代码很好的实现这个效果:backdrop-mask-composite(codepen.io)大家可能已经发现,上面例子中的圆是用svg绘制的,还使用了mask合成,看似比较繁琐,其实这是一种更通用的方案,可以带来无限可能。比如我需要一个星星??镂空效果,很简单,先通过绘图软件画一个然后转义这个svg代码,这里推荐使用张新旭老师的SVG在线压缩合并工具来代替它与刚才的例子.wrap::before{content:'';位置:绝对;宽度:100%;高度:100%;左:0;顶部:0;-webkit-mask:url("data:image/svg+xml,%3Csvgwidth='96'height='91'viewBox='009691'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Cpathd='M480l11.22634.55h36.327l-29.3921.352L77.3990.454869.09818.6190.45129.83755.9.44734.55h=C46.32'C4%C-线性'48'/%3E%3C/s,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)}星星镂空效果如下:完整代码可以查看:backdrop-star(codepen.io)又是一个心形?的例子,实现效果如下完整代码可以查看:backdrop-heart(codepen.io)只能想象,没有不可能7.总结与描述以上实现了一个鼠标跟随空心的效果,从简单到复杂,从单一到通用,虽然借助了一点JS,但只是“工具人”的角色,所有的交互逻辑由CSS完成。总结如下:一个足够大的阴影就是一个实现圆形形状镂空效果的小技巧CSS渐变也可以轻松画出圆形的镂空背景借助CSS变量,非常方便的使用鼠标定位达到想要的效果.backdrop-filter可以想象成毛玻璃的功能。CSSMask可用于绘制磨砂玻璃。打孔,实现镂空的效果借助mask合成特性和SVG,可以实现任意形状的镂空效果CSSMASK还是很强大的,要多掌握最后,如果你觉得不错,对你有帮助,点个赞,收藏,转发???