当前位置: 首页 > 科技观察

一篇文章带你了解奇妙的CSSMASK

时间:2023-03-12 20:54:12 科技观察

本文将介绍CSS中一个非常有趣的属性掩码。mask顾名思义,翻译为面具。在CSS中,mask属性允许用户通过屏蔽或裁剪图像的特定区域来隐藏元素的部分或全部可见区域。其实面具已经有一段时间了,只是实际应用场景不多,在实战中也很少用到。本文将列出一些使用掩码创建的有趣场景。语法是最基本的。mask的使用方法是使用图片,像这样:{/*Imagevalues*/mask:url(mask.png);/*使用位图作为遮罩*/mask:url(masks.svg#star);/*使用SVG图形中的shape做mask*/}当然,图片的使用方式后面会讲到。图片的使用方式其实还是比较繁琐的,因为我们要先准备好相应的图片素材。除了图片,mask还可以接受一个类似于background的参数,那就是gradient。类似下面的使用方法:{mask:linear-gradient(#000,transparent)/*使用渐变做mask*/}如何使用呢?一个很简单的例子,上面我们创建了一个从黑色到透明的渐变颜色,我们在实践中使用它,代码如下所示。下图叠加了从透明到黑色的渐变,{background:url(image.png);mask:linear-gradient(90deg,transparent,#fff);}应用mask后,会变成这样:在这个DEMO中,可以简单了解mask的基本用法。这里说下使用mask最重要的结论:图像的重叠部分和mask生成的渐变透明会变成透明的。值得注意的是,上面的渐变使用的是linear-gradient(90deg,transparent,#fff),这里的#fff纯色部分其实可以换成任何颜色都不影响效果。CodePenDemo--MASK[1]的基本使用。使用MASK进行图像裁剪利用上面的简单应用,我们可以使用mask来实现简单的图像裁剪。使用mask实现图像缺口mask使用线性渐变,我们实现一个简单的缺口图形:.notching{width:200px;高度:120px;背景:线性渐变(135deg,透明15px,deeppink0)左上,线性渐变(-135deg,透明15px,deeppink0)右上,线性渐变(-45deg,透明15px,deeppink0)右下,线性-gradient(45deg,transparent15px,deeppink0)bottomleft;背景大小:50%50%;background-repeat:no-repeat;}是这样的:我们把上面的渐变应用到蒙版上,把背景换成一张图片,得到一张有切角效果的图片:background:url(image.png);遮罩:线性渐变(135deg,透明15px,#fff0)左上,线性渐变(-135deg,透明15px,#fff0)右上,线性渐变(-45deg,透明15px,#fff0)底部右,线性渐变(45deg,透明15px,#fff0)左下角;遮罩尺寸:50%50%;掩码重复:不重复;得到的效果如下:CodePenDemo——使用MASK实现图像角点遮蔽[2]。当然,还有很多其他的方式可以实现上面的效果,比如clip-path,这里的mask也是一种方式。对多张图片使用mask以上是对单张图片使用mask的效果。一起来看看多图下能和面具碰撞出怎样的火花吧。假设我们有两张图片,使用mask,可以很好的叠加显示。最常见的用法:div{position:relative;背景:url(image1.jpg);&::before{位置:绝对;内容:””;上:0;左:0;右:0;下:0;背景:url(image2.jpg);遮罩:线性渐变(45deg,#00050%,透明50%);}}两张图片,一张完全重叠,然后使用mask:linear-gradient(45deg,#00050%,transparent50%)拆分两张图片:CodePenDemo--MASK的基本使用,多张图片下的基本使用[3].当然,注意我们上面使用的mask的渐变是完全的纯色变化,没有过多的效果。我们稍微修改一下mask中的渐变:{-mask:linear-gradient(45deg,#00050%,transparent50%)+mask:linear-gradient(45deg,#00040%,transparent60%)}得到图1转图2效果:CodePenDemo--MASK的基本使用,多张图片的基本使用2[4]。使用MASK做转场动画就有上面的铺垫。利用上面介绍的一些方法,我们可以使用mask来进行一些图片之间的过渡动??画。使用线性渐变mask:linear-gradient()来切换还是上面的Demo,我们动态改变mask的值来实现图片的显示/过渡效果。代码可能如下所示:div{background:url(image1.jpg);动画:maskMove2slinear;}@keyframes{0%{mask:linear-gradient(45deg,#0000%,transparent5%,transparent5%);}1%{mask:linear-gradient(45deg,#0001%,transparent6%,transparent6%);}...100%{mask:linear-gradient(45deg,#000100%,transparent105%,transparent105%);}}当然,像上面这样一一写起来会很费力,我们通常使用SASS/LESS等预处理器来操作。像这样:div{position:relative;背景:url(image2.jpg)不重复;&::before{位置:绝对;内容:””;上:0;左:0;右:0;下:0;背景:url(image1.jpg);动画:maskRotate1.2s缓入缓出;}}@keyframesmaskRotate{@for$ifrom0through100{#{$i}%{mask:linear-gradient(45deg,#000#{$i+'%'},transparent#{$i+5+'%'},透明1%);}}}可以得到如下效果(显示单张图片和这张图片下的两个Switching):CodePenDemo--MASKlinear-gradienttransition[5]。使用角度渐变mask:conic-gradient()来切换当然除了mask:linear-gradient()之外,还可以使用径向渐变或者角度渐变。使用角度渐变的原理是一样的:@keyframesmaskRotate{@for$ifrom0through100{#{$i}%{mask:conic-gradient(#000#{$i-10+'%'},透明#{$i+'%'},透明);}}}可以实现图片的角淡化/切换:CodePenDemo--MASKconic-gradienttransition[6]。这个技巧,在张新旭的这篇文章中,有更丰富的例子,大家可以一步一步看:你用的CSS过渡动画可以改变[7]。使用这种技术,我们可以实现很多有趣的画面效果。像这样:遮罩碰撞过滤器和混合模式继续下一节。CSS中很多有趣的属性,结合滤镜和混合模式,会碰撞出更多的火花。mask&filterfilter:contrast()首先,我们使用多个径向渐变来实现这样一张图片。{背景:径向渐变(#000,透明);background-size:20px20px;}看起来没什么特别的,我们用filter:contrast()对比滤镜来改造一下。代码大概是这样的:html,body{width:100%;高度:100%;过滤器:对比度(5);}div{位置:相对;宽度:100%;高度:100%;背景:#fff;&::before{内容:"";位置:绝对;顶部:0;右:0;底部:0;左:0;背景:径向渐变(#000,透明);背景大小:20px20px;可以得到这样的图形,使用对比滤镜可以使图形非常锐化。这时候我们会叠加不同的mask。可以获得各种有趣的图形效果。body{filter:contrast(5);}div{position:relative;背景:#fff;&::before{背景:径向渐变(#000,透明);背景大小:20px20px;+mask:linear-gradient(-180deg,rgba(255,255,255,1),rgba(255,255,255,.5));}}CodePen演示——使用带滤镜对比度的遮罩[8]。我们叠加了一个线性渐变遮罩linear-gradient(-180deg,rgba(255,255,255,1),rgba(255,255,255,.5)),注意两种渐变颜色都是透明的。或者改为径向渐变:{mask:repeating-radial-gradient(circleat35%65%,#000,rgba(0,0,0,.5),#00025%);}CodePenDemo--使用掩码与过滤器对比度相匹配[9]。好的,下一步,和上面类似,我们添加动画。div{...&::before{背景:径向渐变(#000,透明);背景大小:20px20px;面具:重复径向渐变(圆圈在35%65%,#000,rgba(0,0,0,.5),#00025%);动画:maskMove15s无限线性;}}@keyframesmaskMove{@for$ifrom0through100{#{$i}%{mask:repeating-radial-gradient(circleat35%65%,#000,rgba(0,0,0,.5),#000#{$i+10+'%'});}}}看,你可以得到很酷炫的动画效果:CodePenDemo——usemaskwithfiltercontrastandanimation[10]。请记住使用filter:hue-rotate()作为色调过滤器。再加上它,我们也可以让颜色发生变化。CodePenDemo——使用带有滤镜对比度和动画的遮罩2[11]。mask&filterfilter:contrast()&blendingmode接下来我们叠加混合模式。注意上面,我们的容器背景颜色实际上是白色#fff。我们可以通过多嵌套一层、添加容器背景色、叠加混合模式来创建不同的效果。不要先添加和使用mask,重构结构。最终伪代码如下:

.wrap{position:relative;高度:100%;背景:线性渐变(45deg,#f44336,#ff9800,#ffeb3b,#8bc34a,#00bcd4,#673ab7);}.inner{height:100%;背景:#000;过滤器:对比度(700%);混合混合模式:相乘;&::之前{内容:“”;位置:绝对;顶部:0;右:0;底部:0;左:0;背景:径向渐变(#fff,透明);背景大小:12px12px;}}原理示例图如下:我们可以得到如下效果:OK,此时mask还没有使用,我们来添加mask。.wrap{背景:线性渐变(45deg,#f44336,#ff9800,#ffeb3b,#8bc34a,#00bcd4,#673ab7);}.inner{...过滤器:对比度(700%);混合混合模式:相乘;&::before{背景:径向渐变(#fff,透明);背景大小:12px12px;+mask:线性渐变(#000,rgba(0,0,0,.5));}}CodePen演示——掩码和过滤器以及混合模式[12]。实际效果比截图好多了,可以点击Demo看看。当然,这里叠加的是mix-blend-mode:multiply,大家可以尝试其他的混合模式,得到其他不同的效果。比如overlaymix-blend-mode:difference等:比较有趣的overlay,有兴趣的同学需要自己多尝试。面具与图片当然,面具最本质的作用应该还是在图片上。上面得到的重要结论:图像的重叠部分和mask生成的gradienttransparent会变成透明的。它也可以应用于在mask属性中传递的图像。也就是说mask可以传入image素材中,它会根据background-image和mask图片的透明重叠部分变透明。使用这个技巧,可以做出很酷的转场动画:这里主要是在蒙版中使用这样一张图片:然后,使用逐帧动画快速切换每一帧的蒙版:.img1{background:url(image1.jpg)左上角不重复;}.img2{mask:url(https://i.imgur.com/AYJuRke.png);遮罩尺寸:3000%100%;动画:maskMove2ssteps(29)infinite;}.img2::before{background:url(image2.jpg)no-repeatlefttop;}@keyframesmaskMove{from{mask-position:00;}到{掩码位置:100%0;}}CodePenDemo--遮罩制作过渡动画[13]。当然这也可以加上各种动画。上面已经演示了很多次,有兴趣的同学可以自己尝试一下。最后说了这么多,mask其实是一个比较冷门的属性。在日常业务中使用它的机会并不多。而且兼容性不是特别好。打开MDN可以看到,除了mask本身,还有很多与mask相关的属性,但大部分还处于实验室阶段。本文仅简单介绍掩码本身,与掩码相关的一些属性将另文介绍。当然,即便如此,从属性本身来说,我觉得mask还是很有意思的,给CSS带来了更多的可能性。好了,本文到此结束,希望对你有所帮助:)参考[1]CodePenDemo——MASK的基本使用:https://codepen.io/Chokcoco/pen/YzwZbLQ。[2]CodePenDemo--使用MASK实现图像角点遮蔽:https://codepen.io/Chokcoco/pen/eYJgOxB。[3]CodePenDemo--MASK的基本使用,多图下的基本使用:https://codepen.io/Chokcoco/pen/ZEQeNad。[4]CodePenDemo--MASK的基本用法,多图下的基本用法2:https://codepen.io/Chokcoco/pen/RwrQwXG。[5]CodePen演示——MASK线性梯度过渡:https://codepen.io/Chokcoco/pen/RwrpmyL。[6]CodePen演示——MASK圆锥梯度过渡:https://codepen.io/Chokcoco/pen/eYJVmZX。[7]可以更改你使用的CSS过渡动画:https://www.zhangxinxu.com/wordpress/2019/05/css-transfer-animation/。[8]CodePenDemo——使用带过滤器对比度的掩码:https://codepen.io/Chokcoco/pen/mdVeRVp。[9]CodePenDemo——使用带过滤器对比度的掩码:https://codepen.io/Chokcoco/pen/GRoQZLa。[10]CodePenDemo——使用带有过滤器对比度和动画的掩码:https://codepen.io/Chokcoco/pen/YzweqbB。[11]CodePenDemo——使用带滤镜对比度和动画的掩码2:https://codepen.io/Chokcoco/pen/JjGpKjB。[12]CodePen演示——蒙版和滤镜和混合模式:https://codepen.io/Chokcoco/pen/JjGpWWd。[13]CodePenDemo--maskmake过渡动画:https://codepen.io/Chokcoco/pen/rNxeKRZ。[14]Github——iCSS:https://github.com/chokcoco/iCSS。