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

CSS&SVG绘制书写网格线的三种方式

时间:2023-03-14 09:07:41 科技观察

最近有同事问我这样一个问题:自适应文字需要绘制书写网格线,设计稿是这样的。书写格子实际上就是一行虚线,要求如下:虚线的垂直间隔要自适应跟随行高,保证文字在每一列的虚线上。虚线后面的背景是动态的,可以是纯色、渐变或图片。画这样一条虚线看似容易,其实暗藏玄机。我们来看看实现方法。1.纯色背景下的虚线我们先来看这种简单的情况,可以通过两层渐变覆盖来实现。假设文字行高为2,水平方向优先绘制。body{background:linear-gradient(#6661px,transparent0)0-1px/100%2em;}注意这里的背景大小为100%2em,高度跟随文本行的高度,所以高度为2em,效果如下:然后,画一条垂直的实线覆盖。为了区分,先用浅红色代替。body{background:linear-gradient(toright,#ffdbdb4px,transparent0)0-4px/8px100%,/*垂直*/linear-gradient(#6661px,transparent0)0-1px/100%2em;/*Horizo??ntal*/}这样就以4px的间隔用虚线绘制了一个垂直的tile。效果如下:应该比较容易理解,就是两个方向的梯度叠加。然后,把这个红色改成和底色一样的颜色,比如这里的白色。body{background:linear-gradient(toright,#fff4px,transparent0)0-4px/8px100%,/*垂直*/linear-gradient(#6661px,transparent0)0-1px/100%2em;/*horizo??ntal*/}这样就实现了纯色下的虚线网格,效果如下:2、如果渐变背景下的虚线不是纯色,而是渐变怎么办?假设有这样一个背景。如果直接使用前面的方法,可能会变成这样。白色直接盖住了后面的渐变背景。那么如何解决这个问题呢?像这样叠加混合的情况下,一般会想到混合模式。是的,这里的混音模式也可以轻松搞定。要使用混合模式,两层背景必须在不同的容器中,然后使用mix-blend-mode。html{背景:线性渐变(45deg,#f5ffc0,#fff);}正文{字体大小:20px;背景:线性渐变(向右,#fff4px,透明0)0-4px/8px100%,线性渐变(#6661px,透明0)0-1px/100%2em;mix-blend-mode:darken;}这里我们在混合模式中使用了darken,这种模式可以去除白色部分,保留其他部分,效果如下:完整代码可以在以下任一链接查看:CSS点线混合模式(juejin.cn)[1]CSS点线混合模式(codepen.io)[2]CSS点线混合模式(runjs.work)[3]3.绘图通过圆锥渐变下面介绍一种比较硬核的绘制方法:圆锥渐变(conic-gradient)[4]。为什么说它更硬核呢?因为这样画出来的图形完全是虚线,而且对混合模式没有任何限制。首先我们图形化分析,找到最小的重复单元,如下:找到了,就是这个,其实就是左上角的那个矩形,那么锥形渐变怎么画呢?注:可能有同学会疑惑,这样的矩形线性渐变不是很容易实现吗?确实可以,但是只能实现一个,不能平铺。好像没有关系。下面将带你一步步来。第一种是最原始的语法。div{background:conic-gradient(#666,transparent);}这是一个从透明到灰色的渐变,效果如下:这就是圆锥渐变的样子!然后,我们可以调整渐变的分割线。div{background:conic-gradient(#66690deg,transparent0deg);}这变成了一个边界清晰的正方形。然后通过from关键字改变起始角度。div{background:conic-gradient(from270deg,#66690deg,transparent0deg);}这样起始角度将从270deg开始,如下:接下来改变中心点的位置,水平和垂直居中为默认情况下,我们要改为左上角,需要使用at关键字div{background:conic-gradient(from270degat40px10px,#66690deg,transparent0deg);}这里改为40px,10px在上左上角,如下:最后,更改背景的大小,默认为100%宽高,我们需要更改为实际需要的大小。div{背景:圆锥渐变(从270degat40px10px,#66690deg,透明0deg);background-size:80px90px;}这样会自动平铺展开,如下:原理是这样的,实际虚线比较小,应该是4px1px,所以实际应用应该是这样的。div{背景:圆锥渐变(从270degat4px1px,#66690deg,transparent0deg);background-size:8px2em;}效果如下:完整代码可以在以下任一链接查看:CSS点线圆锥渐变(juejin.cn)[5]CSS点线圆锥渐变(codepen.io)[6]CSSdot-lineconic-gradient(runjs.work)[7]四、动态SVG背景绘制最后给大家介绍一种最容易实现最好的方式就是“切图”。不过这个“切图”与一般的切图不同,因为尺寸是动态的,随着文字的行高而变化,所以需要采取一定的“措施”。先在绘图软件中画出这样一个图形,例如下面是在figma中绘制的。外面的宽高无所谓,随便设置即可。你可以获得这样的SVG。然后,我们将这个svg转换为内联CSS格式。推荐张新旭老师的在线转换工具:SVG在线压缩合并工具[8]。直接放在背景上。正文{字体大小:20px;background:url("data:image/svg+xml,%3Csvgwidth='10'height='10'viewBox='001010'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Cpathd='M00h10v10H0z'/%3E%3Cpathfill='%23D9D9D9'd='M00h5v1H0z'/%3E%3C/svg%3E")00/10px2em;}效果如下:为什么这里的虚线错位了?这也是SVG与传统图像的区别。外部背景尺寸超过viewbox尺寸后,SVG画布会整体缩放,但具体元素不会。具体表现是这样的。那么,有没有办法在画布缩放的时候,让元素保持在左上角呢?当然也可以这样,只要把viewbox改成00100%100%,或者干脆删掉(默认是100%),把SVG的宽高改成100%,如下:这样无论背景大小如何变化,里面虚线的位置都不会受影响,效果如下:完整代码可以查看以下任意链接svg点线(juejin.cn)[9]svg点线(codepen.io)[10]svg点线(runjs.work))[11]除了上面的方法,你还可以换一种思路,让默认的虚线居中,这样放大后也居中,不改变viewbox也可以达到同样的效果as如下。有兴趣的朋友可以下去试一试。5.总结优缺点上面介绍了3种完全不同的虚线绘制方式。原理不同,也各有优缺点。让我们在下面总结一下。CSS渐变混合模式的优点是实现思路比较简单,容易让人觉得首选纯色背景。缺点是混合模式有一些限制。例如,可能需要在黑色背景下更改为不同的模式。CSS锥形渐变的优点是代码实现简单,不受结构限制。缺点是有点难理解,兼容性稍差。SVG自适应背景的优点是使用方便,基本相当于“切图”。缺点是需要掌握SVG的特性,不能直接通过CSS改变颜色,只能改变图片。一般来说,如果对兼容性没有要求,首先推荐第二种方式,其次是SVG方式,最后是混合方式。参考文献[1]CSS点线混合模式(juejin.cn):https://code.juejin.cn/pen/7185780439276060730。[2]CSS点线混合模式(codepen.io):https://codepen.io/xboxyan/pen/ExpNBPr。[3]CSS点线混合模式(runjs.work):https://runjs.work/projects/a0ec6e9e89f943a2。[4]圆锥梯度:https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient。[5]CSS点线圆锥梯度(juejin.cn):https://code.juejin.cn/pen/7185788769595818042。[6]CSS点线圆锥梯度(codepen.io):https://codepen.io/xboxyan/pen/GRBNbEN。[7]CSS点线圆锥梯度(runjs.work):https://runjs.work/projects/dc01e87b2c62426b。[8]SVG在线压缩合并工具:https://www.zhangxinxu.com/sp/svgo/。[9]svg点线(juejin.cn):https://code.juejin.cn/pen/7185803705722077219。[10]svg点线(codepen.io):https://codepen.io/xboxyan/pen/eYjBwxa。[11]svg点线(runjs.work):https://runjs.work/projects/c725bbf1830743b6。