D3js-绘制SVG

另外一个网站:http://www.webhek.com/svg/

现在,我们已经熟悉了SVG图像的基本结构和元素,那么,应该怎样用数据生成图形呢?

你可能已经注意到,SVG元素的所有属性都是标签内属性的形式。即,它们在标签内表示为属性/值的二元组,比如

<element property="value"/>

看起来非常像HTML吧!

<p class="eureka">

之前,我们已经用了D3的常用方法append()attr()来生成新的HTML元素,并设置它们的属性。因为SVG元素也属于DOM,因此和HTML元素没什么两样,所以,我们也可以以完全一样的方式来使用append()attr()来生成SVG图像。

生成SVG

首先,我们需要生成一个SVG元素,它是所有SVG图形的容器。

d3.select("body").append("svg");

这句代码的意思是,找到body元素,然后,将svg元素刚好插到结束标签</body>之前。这么写自然没什么问题,但是我建议把返回值保存下来:

var svg = d3.select("body").append("svg");

因为D3中的大部分方法都返回它所操作的元素的引用,这里的svg变量是append()的返回的一个引用。不要把svg仅仅视为是一个变量,而要把它看成是刚创建的新的SVG对象。这个引用可以让你少写很多代码,因为你没必要每次都去搜索SVG,比如d3.select("svg"),而只需要用指定的这个svg对象。

svg.attr("width", 500)
   .attr("height", 50);

当然,你完全可以将上面的两句代码合为一体。

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 50);

结果测试页中什么也看不到,但是你确实可以通过web inspector看到DOM中有一个空的SVG元素。

为了舒服一点,我建议将宽度和高度值存为变量,放在代码开始醒目的位置,比如(测试页面)

//Width and height
var w = 500;
var h = 50;

我后面所有的示例都保持了这个习惯。图像大小存成变量后,可以方便后续代码中的引用,比如

var svg = d3.select("body")
            .append("svg")
            .attr("width", w)   // <-- Here
            .attr("height", h); // <-- and here!

用变量存储常用数值,是编程的惯用做法。如果你向上苍请愿将整个世界变量化,我会非常乐意签上我的名字的。

数据驱动的形状

现在是时候画一些图形形状了。还是使用原来的简单数据集。

var dataset = [ 5, 10, 15, 20, 25 ];

然后,使用data()来遍历这些数据点,让每个数据点生成一个circle

svg.selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle");

再次强调,selectAll()返回的是所有圆的空引用(这些圆此时并不存在),data()将我们的数据绑定到我们将要创建的元素上,而enter()返回的是新元素的占位元素的引用,最后,append()添加一个circle到DOM中。

为了便于后面的代码再次引用所有的这些圆,我们可以用一个变量将它们的引用存起来。

var circles = svg.selectAll("circle")
                 .data(dataset)
                 .enter()
                 .append("circle");

圆倒是生成了,但它需要设置其位置和大小。下面的代码才是真正出奇迹的地方,

circles.attr("cx", function(d, i) {
        return (i * 50) + 25;
    })
    .attr("cy", h/2)
    .attr("r", function(d) {
        return d;
    });

对着测试页面膜拜一下。我们再逐行理解这句代码。

circles.attr("cx", function(d, i) {
    return (i * 50) + 25;
})

这段代码的意思是在所有圆的引用上为每个圆设置cx年属性。我们的数据已经绑定到了circle元素上,所以对于每个circle,值d对应于数据集(5,10,15,20,25)中的某个值。而另一个参数i,也会自动地累加,也就是变成数据点的序号。比如,第1个圆的i为0,第2个为1,依此类推。这里,i的作用是让圆的中心坐标递增,从而从左至右排列,因为i的值是一直增大的。

(0 * 50) + 25 returns 25
(1 * 50) + 25 returns 75
(2 * 50) + 25 returns 125
(3 * 50) + 25 returns 175
(4 * 50) + 25 returns 225

为了确保i在函数体中可用,你必须让它成为函数定义的一个参数(function(d,i))。而且,前面的d也不能省,即使你并没有用到它。否则,函数会将第1个参数视为d,即数据点的值。

下一行代码是

.attr("cy", h/2)

其中,h是整个SVG图像的高度,所以h/2是半高。这样的效果是让所有的圆都排列在图像垂直方向的中间。

.attr("r", function(d) {
    return d;
});

最后,每个圆的半径r被设置为d,即对应的数据点的值。

漂亮的颜色

填充颜色和线划颜色只是另外两种属性,所以,你可以用同样的方法来设置。比如通过下面的代码

.attr("fill", "yellow")
.attr("stroke", "orange")
.attr("stroke-width", function(d) {
    return d/2;
});

于是,我们得到下面的图像(测试页面)

当然,你可以混合和组合各种属性,并定制各种各样的函数来设置属性。数据可视化的技巧本来就在于选择合适的映射,以便让你的数据的视觉表现派上用场,并被用户所理解。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值