D3带有JSON数据的可重复使用的多线图表

时间:2014-02-03 21:49:20

标签: json d3.js

我正在尝试对我的图表进行一些重新分解,以便将其作为指南重新使用:http://bost.ocks.org/mike/chart/

我在绘制多线图中的线时遇到问题 - 特别是将数据传递给x和y值。如果我硬编码它的元素名称,但如果我尝试使用xValue和yValue对象,这不起作用。我假设这是因为我试图在另一个对象的参数内调用一个函数,但我不知道如何解决这个问题。在exmaple中,Mike使用d [0]和d [1],但这不适用于JSON数据(或者我不确定如何使其工作)。

我已发布此JSFiddle,因此您可以看到代码。问题行是125到131,而这又是从第165行调用的。

var main_line = d3.svg.line()
    .interpolate("cardinal")

    // Hard coding the elements works
    //.x(function(d) { return main_x(d.date); })
    //.y(function(d) { return main_y(d.buildFixTime); });

    // Passing xValue and yValue does not work
    .x(function(d) { return main_x(xValue); })
    .y(function(d) { return main_y(yValue); });

http://jsfiddle.net/goodspeedj/fDyLY/

提前谢谢。

2 个答案:

答案 0 :(得分:2)

您需要在.x()和.y()中重新定义访问器方法。访问器方法定义了从绑定到您调用行生成器的选择的数据中拉出数据的方式。

假设您拥有相对扁平的数据结构,例如以下内容。

data = [{x : 1, y : 2}, {x:1, y:3}, {x:4, y:5}];

然后使用以下语句将数据绑定到选择

d3.select("body").datum(data).append("path").attr("d",lineGenerator);

这句话下面还有一点点。在向您展示一个常用示例后,我会再给您一些演练。

要理解的重要方面是与d3中的其他调用类似,例如

var exampleRectangles = d3.select("body")
.data(data).enter()
.append("rect")
.attr("width",2)
.attr("height", 3)
.attr("x",function(datum){return datum.x}) // pay attention to this line
.attr("y",0);

d3隐式迭代数据中的每个元素。对于数据数组中的每个数据,在这种情况下总共有三个数据,您将在dom中添加一个矩形。

在我告诉你注意的那一行中,你注意到你正在定义一个匿名(未命名)函数。那个datum参数是什么来的?它被隐含地传递给你的匿名函数。

因此每个矩形分别具有自己对应的基准{x:1,y:2},{x:1,y:3},{x:4,y:5}。每个矩形的x坐标由相应的datum.x属性定义。在工作表下,d3隐式循环遍历您定义的数据数组。示例d3代码的类似方法可以如上所述编写。

for (var i = 0; i < data.length; i++)
{

   d3.select("body").append("rect")
    .attr("width",2)
    .attr("height", 3)
    .attr("x",data[i].x)
    .attr("y",0);
}

这源于数据驱动文档(d3)的概念。对于添加的每个项目(上面示例中的一个矩形,一段数据与之相关联。在上面的示例中,您会看到有类似于.x().y()访问者函数的内容:< / p>

.attr("x",function(datum){return datum.x})

这个函数告诉d3如何过滤传递给.attr()访问器方法的总数据。

因此,您需要确定需要哪些数据才能生成.attr(“d”,lineGenerator)call make sense. The difference between your。datum(data)call and the typical。data(data) call is that instead of parceling the data that's being passed to。data(data)`,整个数组作为单个数据给予行生成器函数(类似于main_line(数据),其中它将再次隐式循环遍历点以构建路径。

因此,您需要做的是确定将为您的函数操作定义单个数据的内容。

我不打算定义它,因为我似乎不知道您正在操作哪些信息,但我会猜测类似的东西。

.x(xAccessor)
.y(yAccessor)

function xAccessor(datum)
{
return xScale(datum._id.month);
}

function yAccessor(datum)
{
return yScale(datum.buildFixTime);
}

答案 1 :(得分:1)

您设置的方式,xValueyValue是功能;你必须在某些东西上实际执行它们才能获得价值。

.x(function(d) { return main_x( xValue(d) ); })
.y(function(d) { return main_y( yValue(d) ); });

如果您没有使用比例尺,可以使用

.x(xValue)
.y(yValue);

因为如果你传入一个函数,d3会以数据作为参数为你执行。并且这仅适用于期望函数作为可能输入的d3方法 - 缩放函数期望数据值作为输入。

我上周为另一位用户撰写了一篇很长的文章,你可能觉得它很有用,explaining methods that accept functions as parameters