超详细SVG实战——徒手画pipeline,带你玩转SVG

记录个 svg 实战应用~最近断断续续在搞公司的前端发布平台,本想搞 pipeline ,结果先给 svg 给拦下了。基于发布平台没有同时多项目发布的能力,so~笔者决定搞个 pipelinejenkinsfreeStyle job 给串起来,实现并、串行前端发布的能力。本着身为前端开发的角色,界面肯定是不能少的,于是就有了以下的故事…

笔者也不卖关子了,直接上图!如图,这就是流水线板块的成品样子了。哈哈哈,丑是丑了点,凑合看吧~本文将以笔者自己的业务场景为案例,记录一下如何使用 svg实现直、曲线段,箭头,圆圈来实现这种流水线效果

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第1张图片

熟悉 DevOps 的同学这种界面一定不会陌生,笔者也是照猫画虎搞了个。其实就是把每一个 card 通过各种线段连接起来了,前端看起来会协调一点。这里笔者把 线段部分 给干掉,这样上下一对比,果然还是差了点呀~

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第2张图片

回到主题 svg ,笔者做前端这么久了也只知道有 svg 的存在,实际并没有在实战中自己玩过,最最最接近实战 svg 的时刻,应该就是导出个 svg图标 应用在项目里了~趁着这次搞 pipeline 的机会,直接搞搞 svg ,来个顺手牵羊,美哉美哉~

从笔者的学习到应用来说,使用 svg 做图标、画线并不困难,可能更多时候你不是在搞svg,而是在计算各种点位,就是数学计算而已!本文不是文档,不会直接丢出一大堆api,防止出现看了跟没看一样的效果。本文就用笔者的实现,带着大家过一遍实战。所以大家不用抗拒,花个10来20分钟了解下实战应用,一定对 svg 有自己的理解。接下来,马上进入正题!

一、svg 基本使用

首先看看 MDN 对 svg 的定义:一种基于 XML 的标记语言,用于描述基于二维的矢量图形。其放大、缩小都不会失真,还算是很不错的。只要掌握了 svg 的使用方法,我们可以轻松的用它来实现一些小图标,小logo,还是非常方便的。

首先看一下本文所需要用到的 svg 相关标签元素

  • 用于包裹着整个矢量图。像 :直线、:圆、:矩形等各种svg图形都是被包裹在 标签内的。* 定义路径。这是本文的重点!可以理解为:指定坐标点,指定他们的连接方式。以此,我们就能构建出任何图形,比如一些曲线,各种折线、曲直线结合。* 圆形元素。这个我们仅记一点即可:圆心(cx, cy) + 半径®~* 标记。我们可以用它,在 的起点、终点添加一些图形。比如案例中的小圆圈,小箭头,都是用这个标签实现的。它需要包裹在 元素中。* 用于实现svg的复用,其内容不使用时是不可见的。将需要复用的图形用该标签包裹,通过 标签来使用即可。这个跟下面结合 标签一起举个例子就明了了。* 其实就是 group 的意思,也就是一个集合。我们可以把图形组合用 进行包裹,做一个装箱的包装。以下,直接通过制作一个 “+” 的图标来加深对 标签的理解:

 

这里我们用两个 实现一个“+”,接下来我们用 包裹起两个 并放在 中实现复用

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第3张图片

现在我们用 包裹好,放在 里,页面其实是没有内容的(也就是defs中的内容默认不显示的),如下图:

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第4张图片

最后,我们只需要使用一个 使用即可~效果就不贴了,大家可以复制代码到页面试试。

 
 

哈哈哈,其实讲了点跟本文实现无关的,不过也没关系,多了解点也不错~如果感兴趣的话,大家自己去找找资料看看哈,本文讲的只是冰山一角。在掌握了 基本的用法后,我们接着往下,看看如何实现这种流水线效果~

二、svg 实现曲线

笔者会用从简到繁的方式,一步一步的把曲线画出来,不会直接堆代码和一堆坐标,所以大家跟着走,绝对轻松get。本文主要通过 标签来实现曲线效果,所以我们对这个标签要进行深入一点的了解。

1. path的属性 —— “d”

路径绘制的属性 d :d 这个 属性值其实就是由一堆 “英文字母 + 数字” 组合成的,字母代表指令数字表示坐标。简单点理解:


 

下面看看本文用到的字母指令:

指令 名称 参数
M moveto 移动,用于起始点 x y
L lineto 画直线 x y
Q quadratic Bézier curve 二阶贝塞尔曲线 x1 y1 x y

这里最头疼的可能就是贝塞尔曲线了,还分阶。不过也不用紧张,我们用二阶的就够了,二阶无非也就是在直线的基础上,多了一个偏移点而已。去维基百科搞了个二阶的gif,其实二阶曲线就是在 P0 - P2 这个直线段之间有一个偏移点 P1 ,高阶的贝塞尔曲线也就是直线段中间存在多个偏移点而已,所以二阶的还是比较好理解的。

超详细SVG实战——徒手画pipeline,带你玩转SVG_第5张图片

2. step by step 画曲线

接下来,我们一起画一个这样的曲线:

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第6张图片

为了好理解,这个demo在 100*100 的正方形里面画~

1.首先我们确定一下对角的两个点,先画根直线。起点(0, 0)——终点(100, 100)

 
  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第7张图片

2.上半段路径变成曲线。这个我们不急着动手,先在一个坐标图中画出来就很清晰了

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第8张图片

根据坐标图,我们上半段曲线的偏移点就确定下来了,就是(50, 0)这个点,笔者用深色的虚线模拟了偏移后的曲线,我们把它用 path 的 d 表达出来:

  • 首先起点:M 0 0
  • 偏移点在(50, 0),在(50, 50)结束,我们用二阶贝塞尔曲线表达出来:Q 50 0 50 50
  • 结束点还是:L 100 100
 

这时候我们看看效果:

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第9张图片

这里细心的朋友可能看到了,曲线的开头比后半段的线段要细,这是因为stroke-width为 2px ,所以我们需要让起始点往下多1px,防止线段宽度给吃了。调整后就正常了~

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第10张图片

3.下半段曲线跟步骤2其实是异曲同工的,偏移点是(50, 100),这里就不再演示了,贴出最终的代码:

 

三、实战的实现

首先分析实战中所用到的相关图形:

1.直线
2.曲直线(基于二、svg实现曲线的两段二阶贝塞尔曲线变化而来)
3.路径的起始位置圆圈
4.路径的结束位置箭头
5.其中还有虚线、直线的效果

1. 实现流水线中的曲线效果

案例实现的效果是基于上述曲线的实现进行了一些拓展。因为业务上并行流水线可以有很多,所以每条这种曲线的起始点到终点的距离是变化的,直接应用步骤二的曲线就会出现以下这种情况,并行的任务越多,线段曲度给拉得越平,不是特别美观。

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第11张图片

一个解决的方案就是path中的曲线的曲折程度固定,曲线段之间通过直线连接。也就是伸缩的地方都是直线,曲线的长度、偏折度是固定的。

整体曲线思路大致是这样的:直线 - 圆角曲线 - 直线 - 圆角曲线 - 直线。大致如下图所示

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第12张图片

在 path 中进行表示也就是: M - L - Q - L - Q - L。接下来,笔者在上述曲线的基础上,实现一下这种方式。跟实现曲线时候的步骤一样,我们不急着直接撸码,先通过画图,看看坐标点,捋清晰了坐标再实现就很容易了。

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第13张图片

跟图所示一样,我们的偏折点依然是(50, 0),但是在第一段曲线的起始点(0, 0)和终点(50, 50)之间多了两段标注绿色的平行线,而这就是要被我们用直线替换的地方。他们分别(0,0 - 25,0)(50,25 - 50,50)。接着我们在代码上实现如下:

 

线段效果就出来!这里还得再提醒一下,线段宽度是2px,我们的起始点的y值要是1,不然直线会被吃掉~基于这样,只要我们保证我们曲线段的直线长度、偏折度不变,就能适配案例中的并行流水线的场景啦。接着的下半段线段笔者就不再赘述了,大家有兴趣的话,可以自己把下半段给撸出来哈~

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第14张图片

这里带一笔,案例中实现的虚线是通过css样式控制的:stroke-dasharray。svg的属性,还有一些相关的控制样式,这里不会展开,一方面是太多了,笔者也没精力去整理;一方面是直接丢 api 没场景应用,很容易就忘了,没什么学习效果,就好比背文档没有意义一样。相信有了实现思路,具体实现时再去查找对应的配置、api就行了,实现起来都不会有太大问题~

我们就着上面的曲折线段,搞个虚线试试。给 path 添加样式代码 stroke-dasharray: 6 6;(它是一个数列,数与数之间用逗号或者空白隔开,指定短划线和缺口的长度,哈哈哈,具体大家去看MDN吧)

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第15张图片

接下来,看看 怎么用来做箭头!

2. 使用 在起始、结束点加icon

前面用了点篇幅去描述 defs ,这里算是派上用场了。在本文的场景中,线段的开头,结尾添加了圆圈和箭头。主要实现是把圆圈、箭头实现,再用 进行包裹,添加id,再放在 defs 中。需要添加箭头、圆圈时,通过给标签写样式 marker-end: url(#id) 去使用。大概就是下面这个样子


 

对的,有了 marker 实现这种需求场景非常的便捷。那紧接着,跟大家一起实现一个箭头+圆圈的效果~

1.使用 实现三角箭头
2.使用两个 实现圆圈

实现三角形,我们还是现在坐标轴表示出来。这里我们在尺寸 10 * 10 的正方形中实现~如图所示,我们为三角形找出三个点,接着笔者用 path 中的 d 表示这三个点位

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第16张图片
 

这里的样式跟我们画线的时候有点不同,这里就不是用 stroke 去画的了,而是在标注了三个点位后用了 fill ~这样,我们的等腰三角形就出来!

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第17张图片

紧接着,我们把圆圈也实现一下,其实比起三角就更简单了,两个 circle 拼合起来即可。回顾一下我们属性:圆心(cx, cy) + 半径®。这个我们直接撸代码。圆心都是(5, 5),一个半径3,一个半径4。




 

圆圈效果就出来了~

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第18张图片

最后一步,我们把使用 把我们的箭头和圆圈放在我们的曲线上。let’go!

我们把三角形的 放到 中,并在我们的曲线 中添加样式属性: marker-end: url(#triangle)。代码如下

 

这时候看下页面效果:

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第19张图片

箭头是出现了,但是它并不是对齐终点的正中间的。这时候我们就需要 的另外两个属性 refXrefY 进行位置上的调整。此时,我们只需要把三角上移一半,也就是5px即可。我们调整下 refY

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第20张图片

嗯,没错,这就是我们想要的效果了~

这里,笔者还想引入一个定向 orient="auto" 的属性,虽然在本文中没用到,但是也是个比较方便省事的属性。怎么理解呢,我们在上述demo中,让结尾处线段不水平,让他有一定的水平偏移度,这下箭头还是会指向水平方向。比如下图:

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第21张图片

这里笔者调整下了曲线的终点的Y轴坐标 160(由于超出默认高度,笔者把svg的高度设置成200px),这下子,箭头跟线段的终点在角度上就对不上了,有点奇怪。这时候,我们给 marker 加入 orient="auto" 属性试试效果~

  • 超详细SVG实战——徒手画pipeline,带你玩转SVG_第22张图片

好了,基本上讲到这里就差不多了,开头圆圈的实现也是异曲同工的,也就不再进行演示了~大家有兴趣可以自己尝试一下,加在线段开头需要使用 marker-start ,其他都是一样的用法。


其实整个流水线的ui做出来也并不困难,还是那句,更多是在点位的取值、计算当中度过的。没错!!!笔者觉得比较麻烦的就是各种计算,path的路径d的计算都是放在js中,但是其跟一些css样式是有关联的。比如我的一个card多高,path的终点就需要计算到这个card的高度的一半再加上各种边距。基于这样,怎么做到只调整一个地方的尺寸,就能自动计算到最终的位点也是比较关键的,毕竟很多时候我自己会对一些宽高做微调~

基于这样!笔者用的css变量的方式,将js、css的尺寸相关的数值进行了统一,也不知道还有没有什么更好的方案和办法,哈哈哈期待评论区的你们。本文就不再展开如何统一js、css中的一些样式值了,看看最近有没时间,再单独写一篇文章来进行分享吧~

你可能感兴趣的:(devops,运维)