首页 > 其他分享 >CSS mask 与 切图艺术

CSS mask 与 切图艺术

时间:2024-05-06 09:56:04浏览次数:13  
标签:遮罩 composite 切图 mask webkit CSS fill

一、“切图”的局限性

传统的“切图”简单暴力,但往往缺少适应性。

适应性一般有两种,一是尺寸自适应,二是颜色可以自定义

举个例子,有这样一个优惠券样式

关于这类样式实现技巧,之前在这篇文章中有详细介绍:

CSS 实现优惠券的技巧

不过这里略微不一样的地方是,两个凹陷处都是平滑处理的

单纯实现内凹圆角已经很费劲了,现在还来个平滑圆角?是时候祭出最后大招了--切图。

但是,切图真的能解决吗?假设已经得到了这样一张图片

div{
  background: url(a.png) 0/100% 100%;
}

下面是这张图片在不同尺寸下的表现

除非整个布局的尺寸是完全固定的,否则都会有不同程度的拉伸情况,这是视觉最为忌讳的。

另外,整张图是固定的,也无法直接修改背景色,如果有多种状态,还需要保存多份

.div1{
  background: url(a.png) 0/100% 100%;
}
.div2{
  background: url(b.png) 0/100% 100%;
}

有没有更为灵活的切图方式呢?

二、图形运算与CSS MASK

经常会和设计稿打交道,对设计软件(Photoshop、Figma等)应该或多或少也有所了解了,这里简单介绍一下图形运算(也称布尔运算),通常有 4 种类型

这是一个非常常见的设计技巧,可以将不同的图形经过运算合成新的图形。

下面是一个经典案例,就是通过圆的布尔运算绘制的

这么好的特性,CSS 中有类似的吗?

这就不得不提到CSS mask 了,CSS MASK 可以指定一张图作为遮罩图片。

div{
  mask: url(图片);
  mask: 渐变;
}

遮罩图片可以是图片,也可以是渐变。主要原理是显示遮罩图片不透明的部分,透明的则会被裁剪,示意如下

但是,很多情况下,单一的遮罩并不能满足需求,比如这样一个带缺口的圆,单一的渐变可能无法绘制

因此,我们需要用到和设计中图形布尔运算一样的技巧。

这和 CSS mask中的mask-composite是一一对应的

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

利用这个特性,可以很轻易的合成带缺口的圆,也就是说,我们可以使用 CSS 的方式自由的去裁剪、合成我们想要的图形。

另外,-webkit-mask-composite与标准下的值有所不同,属性值非常多,如下

-webkit-mask-composite: clear; /*清除,不显示任何遮罩*/
-webkit-mask-composite: copy; /*只显示上方遮罩,不显示下方遮罩*/
-webkit-mask-composite: source-over; /*默认值,正常的叠加,等同于 add */
-webkit-mask-composite: source-in; /*只显示重合的地方,等同于 intersect*/
-webkit-mask-composite: source-out; /*只显示上方遮罩,重合的地方不显示,等同于subtract*/
-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; /*只显示不重合的地方,等同于 exclude*/

其实是借用了 Canvas 中的图形合成属性,并且区分了图层顺序,但是对于遮罩层来讲,其实只需要关注遮罩的形状,不要关注图层的颜色,所以上述的一些值效果是完全相同的。

这里可以先不用每个都理解,知道有上面4种类型就行了,其实可以一一去试验,等熟悉了自然就知道每个属性的具体用途了。

下面是每个属性的演示

https://codepen.io/xboxyan/pen/RwKbGwN

了解了这些,接下来看看在切图中的应用。

三、圆滑的内凹圆角

回到前面的问题,同样是切图,不过我们需要换一种方式。

仔细观察,从整体反向考虑,其实就是一个正常的圆角矩形,然后挖去两个平滑的缺口,两个缺口的大小是固定的,位置也是相对不变的,如图所示黑色的部分

所以下面的问题就是,如何来得到这两个缺口

单纯CSS渐变是难以绘制的,所以这里可以直接“切图”。但是设计稿上给的是红色部分,如何去手动做一个缺口部分呢?

这就稍微借助设计工具了,这里以 Figma 为例,我们绘制一个矩形,居右对齐,确保可以覆盖缺口(如下,蓝色部分)

然后,将蓝色矩形图层放在原图形下面

最后,选中这两个图形,执行减去顶层

用同样的方式,可以得到左右两个半圆,或者直接翻转一下也行

接下来,我们需要将这两个 svg 转为内联,推荐用张鑫旭老师的这个

SVG在线压缩合并工具

最后,我们使用3层遮罩,两个半圆加上整个矩形,通过遮罩合成(仅显示不重叠部分)就可以得到我们需要的图形了

这样做的好处是两个半圆是通过CSS定位实现的,所以可以确保一定是居中、靠近边缘的,不会因为尺寸的变化而变形。

下面是完整代码

coupon{
  width: 300px;
  height: 150px;
  border-radius: 8px;
  background: linear-gradient(85deg, #FF9078 7.57%, #FA3440 80.06%);
  -webkit-mask: url("data:image/svg+xml,%3Csvg width='20' height='48' viewBox='0 0 20 48' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 48V0c0 2.21 1.809 3.958 3.974 4.395C13.116 6.238 20 14.315 20 24S13.116 41.762 3.974 43.605C1.81 44.042 0 45.791 0 48z' fill='%23000'/%3E%3C/svg%3E") 0 50%/20px no-repeat,
    url("data:image/svg+xml,%3Csvg width='20' height='48' viewBox='0 0 20 48' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M20 48V0c0 2.209-1.809 3.959-3.975 4.395C6.885 6.238 0 14.315 0 24s6.885 17.762 16.025 19.605C18.191 44.041 20 45.791 20 48z' fill='%23000'/%3E%3C/svg%3E") 100% 50%/20px no-repeat,
    linear-gradient(red 0 0);
  -webkit-mask-composite: xor;
}

这样就得到了尺寸自适应、可更换颜色的优惠券样式了

 

四、投票 PK 样式

下面来看这样一个例子

注意,这里也是有平滑圆角的,并且在宽度改变时,倾斜角是固定的

同样,也可以用“切图”的方式来实现这样的效果

在这里,我们还是从整体考虑,将图形补全,用图形合成的方式,在 Figma 中绘制出如下的“平滑直三角”

然后在 CSS 中通过 mask 减去黑色部分就行了,下面是完整代码

.pk{
  display: flex;
  width: 400px;
}
.item{
  height: 40px;
}
.left{
  width: 50%;
  border-radius: 40px 0 0 40px;
  background: linear-gradient(85deg, #FF9078 7.57%, #FA3440 80.06%);
  -webkit-mask: linear-gradient(red,red), url("data:image/svg+xml,%3Csvg width='16' height='40' viewBox='0 0 16 40' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M16 0h-2.344a1 1 0 0 1 .957 1.287L3.855 37.148A4 4 0 0 1 .023 40H16V0z' fill='%23C6F'/%3E%3C/svg%3E") right/auto 100% no-repeat;
  -webkit-mask-composite: xor;
}
.right{
  flex: 1;
  border-radius:  0 40px 40px 0;
  background: linear-gradient(274deg, #5FB6F5 -3.81%, #4B80EE 62.98%);
  -webkit-mask: linear-gradient(red,red), url("data:image/svg+xml,%3Csvg width='16' height='40' viewBox='0 0 16 40' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 40h2.344a1 1 0 0 1-.957-1.287L12.145 2.85A4 4 0 0 1 15.977 0H0v40z' fill='%23C6F'/%3E%3C/svg%3E") left/auto 100% no-repeat;
  -webkit-mask-composite: xor;
}

这样实现的倾角支持渐变,支持自适应宽度,效果如下

五、平滑 tab 样式

最后再来看一个例子:平滑 tab 标签,就是 Chrome 标签栏那样的

其实关于这个布局,之前也专门写过文章,介绍了5种不同方式,有兴趣的可以回顾一下

CSS 实现Chrome标签栏的技巧

这次再来介绍一个比较简单、实用的“切图”方式。

通过前面两个例子,可能你已经猜到要怎么做了。没错,就是先补全

然后在设计软件中将黑色部分单独“切”出来

然后在 CSS 中通过 mask 减去这两部分黑色部分就行了,和第一个例子非常像,下面是完整代码

tab{
  line-height: 40px;
  padding: 0 30px;
  background-color:royalblue;
  color: #fff;
  -webkit-mask: url("data:image/svg+xml,%3Csvg width='28' height='40' viewBox='0 0 28 40' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28 0H0v40h1c8.283 0 15-6.717 15-15V12c0-6.627 5.373-12 12-12z' fill='%23000'/%3E%3C/svg%3E") 0 0 no-repeat,
    url("data:image/svg+xml,%3Csvg width='28' height='40' viewBox='0 0 28 40' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0h28v40h-1c-8.283 0-15-6.717-15-15V12C12 5.373 6.627 0 0 0z' fill='%23000'/%3E%3C/svg%3E") 100% 0 no-repeat,
    linear-gradient(red 0 0);
  -webkit-mask-composite: xor;
}

这样实现的 tab 既做到了自适应宽度,也能随意更改背景,效果如下

六、总结一下

以上就是本文的全部内容了,介绍了一种特殊的“切图”手法,将切图与CSS MASK结合起来,既保留了“切图”的简单暴力,又满足了CSS自适应的特点,下面简单总结一下

  1. 传统的“切图”简单暴力,但往往缺少适应性:尺寸自适应和颜色自适应
  2. 图形布尔运算主要有:合并形状、减去顶层、交叉形状、排除重叠
  3. CSS MASK composite 刚好也有相同的特性
  4. 可以从整体反向考虑,将难以实现的部分由“切图”完成,然后通过mask从整体减去这一部分
  5. 由于缺口部分是通过CSS定位实现,因此可以确保整体的自适应性

标签:遮罩,composite,切图,mask,webkit,CSS,fill
From: https://www.cnblogs.com/moranjl/p/18096084

相关文章

  • 使用 CSS columns 布局来实现自动分组布局
    最近在项目中碰到这样一个布局,有一个列表,先按照4*2的正常顺序排列,当超过8个后,会横向重新开始4*2的布局,有点像一个个独立的分组,然后水平排列,如下图中序号是 dom 序列,所以其实这这样的一个顺序很多同学可能会想到给子元素分组(通过 JS将原数组拆分组合成一个二维数......
  • CSS 盒模型
    在css中,所有元素都被一个个的"box"包围着,理解这些盒子的基本原理,是实现用css实现精准布局,处理元素排列的关键.标准盒模型盒子模型的组成元素:content:内容区padding:内天成border:边框margin:外边距在标准盒模型中,盒的width/height指......
  • solid在css中什么意思
    solid在CSS中的含义在CSS中,solid是一个用于定义边框样式的关键词。作用solid用于创建一个具有实线边框的元素。实线边框是一种连续且不间断的线条,将其应用于元素周围可强调或定义其边界。语法该关键词用于border-style属性,它用于设置元素边框的样式。该属性的语法如......
  • 2024-05-04 css实现鼠标移动至盒子,盒子在约定时间内进行放大缩小
    放大缩小css@keyframesscaleAnimation{0%{transform:scale(1);}50%{transform:scale(1.2);}100%{transform:scale(1);}}完整代码:<!DOCTYPEhtml><htmllang="en"><head><metacharset=&q......
  • CSS & JS Effect – 用 wheel 模拟 scroll
    前言在用JavaScript实现positionsticky 文章中,我提到了用wheel来模拟scroll效果。这篇来说说具体怎么实现,挺简单的哦。 Preparationtable.html<divclass="container"><table><thead><tr><th>FirstName</th>&l......
  • css-布局-calc()
    <divstyle="display:flex;"><div><menu_left/></div><divstyle="flex-grow:1;"><tables:table_title="table_title":table_content="table_content"@type......
  • CSS Custom Highlight API
    CSSCustomHighlightAPICSSCustomHighlightAPIJavaScript创建范围并使用CSS定义样式来设置文档中任意文本范围的样式该API允许开发者通过CSS自定义属性来设置文本的样式,并将其应用到文档中的任意文本范围。本质就是查找所有文本节点,收集匹配内容的Range,最后......
  • CSS Counter Styles
    CSSCounterStyles允许您自动对HTML文档中的元素进行编号或标记。我们定义一个具有特定名称和起始值的counter,然后根据CSS规则递增或递减该计数器。使用counter-reset属性定义计数器,设置其起始值,然后使用counter-increment属性根据需要递增或递减计数器。还可以使......
  • css中内容content部分垂直居中的方法
     1、vertical-align属性让文字居中  vertical-align值有很多,常用的就是middle,bottom,text-bottom等,然而真实使用的时候,我们会发现这个属性“时灵时不灵”,有些情况下我们加了这个属性之后仍然不见img或者text有任何的变化。那是因为vertical-align只作用在inline-block或者inl......
  • unocss如何使用css变量
    在UnoCSS中,可以直接使用CSS变量来定义样式。但是,UnoCSS本身并不支持直接使用变量名作为类名或选择器。如果想使用CSS变量来定义样式,可以按照以下方式进行操作:在CSS文件中定义一个变量,例如--text-color:red;。在UnoCSS的样式表中,可以通过var()函数来引用该变量,例......