【 D3.js 进阶系列 — 4.0 】 绘制箭头

在 SVG 绘制区域中作图,在绘制直线和曲线时,常需要在某处添加箭头。本文介绍如何在 D3 中给直线和曲线添加箭头。

 401

到目前为止,我们绘制 D3 的图表都是在 SVG 绘制区域内,虽然 D3 也可用 Canvas 或 WebGL 等作图,但 SVG 是最常用的。那么,用 D3 来绘制箭头,先要明白在 SVG 中是怎么绘制的。

1. 在 SVG 中定义箭头的标识

定义箭头的标识如下,先写一对 <defs> ,里面再写一对 <marker>,其中 marker 的属性的意义为:

viewBox 坐标系的区域
refX, refY 在 viewBox 内的基准点,绘制时此点在直线端点上(要注意大小写)
markerUnits 标识大小的基准,有两个值:strokeWidth(线的宽度)和userSpaceOnUse(图形最前端的大小)
markerWidth, markerHeight 标识的大小
orient 绘制方向,可设定为:auto(自动确认方向)和 角度值
id 标识的id号

然后在 marker 里绘制图形即可,下面的代码中用 path 绘制了一个箭头的图形。

 

2. 在 SVG 中绘制箭头

有了上面的标识,就可以绘制箭头了。下面绘制一条线段,在线段末尾添加箭头:

也可以用 path 来绘制:

在不同的位置绘制的属性如下:

  • marker-start :路径起点处
  • marker-mid:路径中间端点处(必须是 path 中间出现的点)
  • marker-end :路径终点处

3. 使用 D3 绘制箭头

有了上面的内容,在 D3 中如何绘制呢?

先定义箭头的标识:

使用上述 marker 绘制箭头的代码为:

结果图为本文开始的图片所示,完整代码为:

SVG版:http://www.ourd3js.com/demo/J-4.0/arrow.svg

D3版:http://www.ourd3js.com/demo/J-4.0/arrow.html

谢谢阅读。

文档信息

【 D3.js 进阶系列 — 4.0 】 绘制箭头》上有14条评论

  1. 用圆和箭头怎么制作流程图d3

  2. 你好,我的线条粗细都是不一样的,可是我想让箭头都是一样的粗细,应该调整什么参数

  3. 请问下:
    svg.selectAll(“line”)
    .data(data)
    .enter()
    .append(“line”)
    .attr(“x1″, function(d) {
    return projection([d.lon, d.lat])[0];
    })
    .attr(“y1″, function(d) {
    return projection([d.lon, d.lat])[1];
    })
    .attr(“x2″, function(d) {
    return (projection([d.lon, d.lat])[0] * Math.sin(d.rad) + projection([d.lon, d.lat])[0]);
    })
    .attar(“y2″,function(d) {
    return (projection([d.lon, d.lat])[1] * Math.cos(d.rad) + projection([d.lon, d.lat])[1]);
    })
    .attr(“stroke-width”,2)
    .atter(“stroke”,function(d){return computeColor(linear(d.speed));})

    这段代码中,d.lon,d.lat为经纬度,d.rad为角度,可是为什么在地图上画不出来呢?

  4. Pingback引用通告: 【 D3.js 高级系列 — 8.0 】 标线 - Web前端 - 阿里欧歌

  5. 标识这部分确实挺有用!感谢老师的讲解!

  6. 你好,我上次箭头显示不出来找到原因了,是因为线先生成所以箭头被覆盖在图片里面,现在换了下顺序看到了,可是线的终点是在图片中心所以箭头就在里面。那么我想在边缘显示图片要怎么办呢。

        • 是指图片的边缘,原来你的那个力图的例子连线的起点和终点是设置在图片的中心,那个maker又是设置在线的终点,所以箭头被包含在图片内部,所以我改变线终点的坐标,可是效果不太好,因为图片出来的时候是随机乱跳的,所以有时候线能搭在图片的边缘,有时候都没指向图片。

          • 这是我的实现,可以解决箭头被图片覆盖的问题

            edges_line.each(function(d) {
            if (true) {
            // Work around IE bug regarding paths with markers
            // Credit: #6 and http://stackoverflow.com/a/18475039/106302
            this.parentNode.insertBefore(this, this);
            }

            var x1 = d.source.x,
            y1 = d.source.y;
            x2 = d.target.x,
            y2 = d.target.y;

            var l=Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
            var l1=20;//箭头方向缩短的长度
            var x3=x1+((l-l1)/l)*(x2-x1);
            var y3=y1+((l-l1)/l)*(y2-y1);

            d3.select(this)
            .attr(‘x2′, x3)
            .attr(‘y2′, y3);
            });

评论已关闭。