起因
最近做需求时发现有个这样的 UI 图
第一眼看到这图时脑子就像着用着几个 div 加 border-radio 来实现,仔细一看发现这个图形整体的背景色是带渐变的,那就不能用几个元素去拼凑了,这只能用于单一背景色的图形。
整体带渐变背景色就需要用一个元素去画出这个图形,但是这太麻烦了,还有一种方法就是使用蒙版。前端中蒙版有 CSS 蒙版,SVG 蒙版,Canvas 蒙版。CSS 蒙版需要引入图片,如果要引入图片那还不如直接叫 UI 把这每个进度的图给我算了,Canvas 又觉得小题大做,所以这里使用 SVG 蒙版。
代码实现
首先画出蒙版图形
<defs> 标签用于自定义形状,它内部的代码不会显示,仅供引用。rx,ry 为矩形圆角边框。
<mask> 标签为遮罩元素,可将 SVG 元素当做蒙版显示,白色为全透明,黑色为不透明。
<defs>
<mask id="small-rect">
<rect x="0" y="30" height="3" width="240" rx="2" ry="2" style="stroke: #70d5dd;"
fill="white" />
<circle cx="30" cy="30" r="6" fill="white"/>
<circle cx="60" cy="30" r="6" fill="white"/>
<circle cx="90" cy="30" r="6" fill="white"/>
<circle cx="120" cy="30" r="6" fill="white"/>
<circle cx="150" cy="30" r="6" fill="white"/>
<circle cx="180" cy="30" r="6" fill="white"/>
</mask>
</defs>
再定义下渐变色
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
再画个矩形,并引入蒙版
<rect id="front" x="0" y="0" width="200" height="50" fill="url(#grad1)" mask="url(#small-rect)"></rect>
注意该元素的位置要在蒙版元素位置内才能看到效果
效果完成
大体上差不多了,在进度显示上只要控制蒙版矩形的宽和圆的个数就可以了。
SVG 还有组的概念,试了下在组上加入渐变,结果不行。
<g> 标签用于将多个形状组成一个组(group)。
<g fill="url(#grad1)">
<rect x="0" y="50" height="3" width="240" rx="2" ry="2" style="stroke: #70d5dd;" />
<circle cx="30" cy="50" r="6"/>
<circle cx="60" cy="50" r="6"/>
</g>
然而不行,相当于在每个元素上加了个渐变。