如何用svg在网页中画一条带箭头的连接线

path命令

SVG中所有基本形状都是path的简写形式,但是建议使用简写形式,因为这样可以使SVG文档更可读。

path元素更通用,可以通过制定一系列相互连接的线、弧、曲线来绘制任意形状的轮廓,这些轮廓也可以填充或者绘制轮廓线,也可以用来定义裁剪区域或蒙版。

下表为path命令总结,其中大写表示绝对坐标,小写表示相对坐标:

命令 参数 说明
M m x y 移动画笔到制定坐标
L l x y 绘制一条到给定坐标的线
H h x 绘制一条到给定x坐标的横线
V v y 绘制一条到给定y坐标的垂线
A a rx ry x-axis-rotation large-arc sweep x y 圆弧曲线命令有7个参数,依次表示x方向半径、y方向半径、旋转角度、大圆标识、顺逆时针标识、目标点x、目标点y。大圆标识和顺逆时针以0和1表示。0表示小圆、逆时针
Q q x1 y1 x y 绘制一条从当前点到x,y控制点为x1,y1的二次贝塞尔曲线
T t x y 绘制一条从当前点到x,y的光滑二次贝塞尔曲线,控制点为前一个Q命令的控制点的中心对称点,如果没有前一条则已当前点为控制点。
C c x1 y1 x2 y2 x y 绘制一条从当前点到x,y控制点为x1,y1 x2,y2的三次贝塞尔曲线
S s x2 y2 x y 绘制一条从当前点到x,y的光滑三次贝塞尔曲线。第一个控制点为前一个C命令的第二个控制点的中心对称点,如果没有前一条曲线,则第一个控制点为当前的点。

路径的填充同样可以使用fill-rule属性指定填充规则,如果需要填充一个中空的形状,则只需要注意外侧路径顺逆时针方向和内侧空心区域顺逆时针方向即可。

绘制一条直线

<path d="M 0,0 L 100,100" />

首先,使用M移动画笔到起点坐标(这里假设是0,0),然后使用L画一条直线至终点坐标(这里假设是100,100)。

image.png

绘制一条贝塞尔曲线

这里使用C来绘制一条三次贝塞尔曲线。
三次贝塞尔曲线的每个控制点都有两个控制点。 因此,要创建三次贝塞尔曲线,需要指定三组坐标。

 C x1 y1, x2 y2, x y 

这里的最后一组坐标(x,y)指定了线的结束位置。另外两个是控制点。(x1,y1)是曲线开始的控制点,(x2,y2)是曲线结束的控制点。控制点本质上描述了从每一点开始的直线的斜率。然后,贝塞尔函数创建了一条光滑的曲线,从建立的斜率在线的开始,到另一端的斜率。


image.png
<path d="M 0,0 C 50,0 50,100 100,100" />
image.png

示例中该条贝塞尔曲线计算公式为

    const startX = 0, startY = 0, endX = 100, endY = 100;

    const yOffset = Math.abs(endY - startY) / 2;
    const centerY = endY < startY ? endY + yOffset : endY - yOffset;

    const xOffset = Math.abs(endX - startX) / 2;
    const centerX = endX < startX ? endX + xOffset : endX - xOffset;

    const pathAttr = `M ${startX},${startY} C ${centerX},${startY} ${centerX},${endY} ${endX},${endY}`;

marker元素

marker元素用来在path上添加一个标记,比如箭头之类的。

首先需要定义好marker元素,然后在path中引用,一个marker标记是一个独立的图形,有自己的私有坐标。

marker属性 说明
markerWidth marker标记的宽度
markerHeight marker标记的高度
refX refY 指定marker中的哪个坐标与路径的开始坐标对齐
orient 自动旋转匹配路径的方向,需要设置为auto
markerUnits 这个属性决定标记的坐标系统是否需要根据path的笔画宽度调整,如果设置为strokeWidth,则标记会自动调整大小。如果设置为useSpaceOnUse,则不会自动调整标记的大小。
viewBox preserveAspectRatio 设置标记的显示效果,比如可以将标记的(0,0)设置在标记网格中心
    <defs>
        <marker id="triangle" markerUnits="strokeWidth" markerWidth="5" markerHeight="4" refX="0" refY="2" orient="auto">
            <path d="M 0 0 L 5 2 L 0 4 z" />
        </marker>
    </defs>
    <path d="M 0,0 L 100,100" stroke="black" stroke-width="2" fill="none"
                style="marker-end: url(#triangle);" />
image.png

首先,我们使用marker画一个箭头。设置orient为auto,使箭头的方向自动旋转匹配路径的方向。
然后,可以在连接线的path中使用marker-start,marker-mid,marker-end,marker属性来设置标记的位置。

  • marker-start 属性将在给定形状的第一个顶点绘制的箭头或多边形标记。

    image.png

  • marker-mid 属性将在给定形状的所有内部顶点绘制的箭头或多边形标记。

    image.png

  • marker-end 属性将在给定形状的最终顶点绘制箭头或者多边形标记。

    image.png

  • marker 属性,则表示同时设置marker-start,marker-mid,marker-end三个属性。

这里,我们使用marker-end在线的结尾加上箭头。

示例

<svg width="100%" height="100%">
        <g transform="translate(0,0) scale(1)">
            <g>
                <defs>
                    <marker id="triangle" markerUnits="strokeWidth" markerWidth="5" markerHeight="4" refX="0" refY="2" orient="auto">
                        <path d="M 0 0 L 5 2 L 0 4 z" />
                    </marker>
                </defs>
                <path d="M 0,0 L 100,100" stroke="black" stroke-width="2" fill="none"
                    style="marker-end: url(#triangle);" />
            </g>
            <g>
                <defs>
                    <marker
                        id="triangle"
                        markerUnits="strokeWidth"
                        markerWidth="5"
                        markerHeight="4"
                        refX="0"
                        refY="2"
                        orient="auto">
                        <path d="M 0 0 L 5 2 L 0 4 z" />
                    </marker>
                </defs>
                <path d="M 100,0 C 150,0 150,100 200,100" stroke="black" stroke-width="2" fill="none"
                    style="marker-end: url(#triangle);" />
            </g>
        </g>
    </svg>
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354