简体   繁体   English

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

[英]D3 reusable multi-line chart with JSON data

I'm trying to do some re-factoring on my charts to make them re-usable using this as a guide: http://bost.ocks.org/mike/chart/ 我正在尝试对我的图表进行一些重新分解,以使它们可以作为指南重复使用: http//bost.ocks.org/mike/chart/

I'm having problems drawing the lines in my multi-line graph though - specifically passing the data to the x and y values. 我在绘制多线图中的线时遇到问题 - 特别是将数据传递给x和y值。 If I hard code the element names it works, but if I try to use the xValue and yValue objects this does not work. 如果我硬编码它的元素名称,但如果我尝试使用xValue和yValue对象,这不起作用。 I'm assuming that this is because I'm trying to call a function within the parameter of an other object, but I'm not sure how to get around this. 我假设这是因为我试图在另一个对象的参数内调用一个函数,但我不知道如何解决这个问题。 In the exmaple Mike uses d[0] and d[1], but this won't work with JSON data (or I'm not sure how to make it work). 在exmaple中,Mike使用d [0]和d [1],但这不适用于JSON数据(或者我不确定如何使其工作)。

I've posted this JSFiddle so you can see the code. 我发布了这个JSFiddle所以你可以看到代码。 The problem lines are 125 to 131 which in turn is being called from line 165. 问题线是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/ http://jsfiddle.net/goodspeedj/fDyLY/

Thank you in advance. 先感谢您。

You need to redefine your accessor method within .x() and .y(). 您需要在.x()和.y()中重新定义访问器方法。 The accessor method defines the way that a datum is pulled out of the data that is bound to the selection that you call the line generator on. 访问器方法定义了从绑定到您调用行生成器的选择的数据中拉出数据的方式。

Suppose you have a relatively flat data structure such as the following. 假设您有一个相对扁平的数据结构,如下所示。

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

You then bind the data to a selection with the following statement 然后使用以下语句将数据绑定到选择

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

Quite a bit is going on underneath this statement. 在这个陈述下面有很多事情要发生。 I'll give you a bit more of a walkthrough after showing you a commonly used example. 在向您展示一个常用示例后,我会再给您一些演练。

The important aspect to understand is that similarly to other calls in d3 such as 要理解的重要方面是与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 is implicitly iterating over each element in your data. d3隐式迭代数据中的每个元素。 For each datum in your data array, in this case there is a total of three datum, you are going to add a rectangle to the dom. 对于数据数组中的每个数据,在这种情况下总共有三个数据,您将在dom中添加一个矩形。

In the line that I tell you to pay attention to you notice that you're defining an anonymous (unnamed) function. 在我告诉你要注意的那一行中,你注意到你正在定义一个匿名(未命名)函数。 What is that datum parameter coming from? 那个datum参数来自哪个? It's implicitly being passed to your anonymous function. 它被隐式传递给你的匿名函数。

So each rectangle has it's own corresponding datum {x : 1, y : 2}, {x:1, y:3}, {x:4, y:5} respectively. 因此每个矩形分别具有自己对应的基准{x:1,y:2},{x:1,y:3},{x:4,y:5}。 Each rectangle's x coordinate is defined by the respective datum.x attribute. 每个矩形的x坐标由相应的datum.x属性定义。 Under the sheets, d3 is implicitly looping over the data array that you've defined. 在工作表下,d3隐式循环遍历您定义的数据数组。 A similar approach to the example d3 code could be written as above. 可以如上所述编写与示例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);
}

This follows from the notion of data driven documents (d3). 这源于数据驱动文档的概念(d3)。 For each item added (a rectangle in the above example a piece of data is tied to it. In the above example you see that there is something kind of similar to your .x() and .y() accessor functions : 对于添加的每个项目(在上面的示例中,一个矩形与一个数据相关联。在上面的示例中,您会看到有类似于.x().y()访问器函数的类型:

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

This function is telling d3 how to filter over the total datum that's being passed to the .attr() accessor method. 该函数告诉d3如何过滤传递给.attr()访问器方法的总数据。

So, you need to determine which data you need to get a hold of to make your .attr("d", lineGenerator) call make sense. The difference between your 因此,您需要确定需要哪些数据才能使.attr(“d”,lineGenerator) call make sense. The difference between your 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)`, the whole array is given as a single piece of data to the line generator function (similar to main_line(data), wherein it will again implicitly loop over the points to construct your path. .datum(数据) call and the typical .data(数据) call is that instead of parceling the data that's being passed to call make sense. The difference between your call is that instead of parceling the data that's being passed to .data(数据)` call is that instead of parceling the data that's being passed to将整个数组作为单个数据提供给行生成器函数(类似于main_line(数据),其中它将再次隐式循环遍历点以构建路径。

So, what you need to do is determine what a single datum will be defined as for your function to operate on. 因此,您需要做的是确定将为您的函数操作定义单个数据的内容。

I'm not going to define that as I don't seem to know quite which information you are operating on, but I would hazard a guess at something like. 我不打算定义它,因为我似乎不知道你正在操作哪些信息,但我会冒险猜测类似的东西。

.x(xAccessor)
.y(yAccessor)

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

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

The way you have it set up, xValue and yValue are functions; 你设置它的方式, xValueyValue是函数; you have to actually execute them on something to get a value back. 你必须在某些东西上实际执行它们才能获得价值。

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

If you weren't using a scale, you could use 如果你没有使用秤,你可以使用

.x(xValue)
.y(yValue);

but only because if you pass in a function d3 executes it for you with the data as a parameter. 只是因为如果你传入一个函数,d3会以数据作为参数为你执行它。 And that only works for d3 methods that expect functions as possible input -- the scale functions expect data values as input. 并且这仅适用于期望函数作为可能输入的d3方法 - 缩放函数期望数据值作为输入。

I wrote a long piece work for another user last week that you may find useful, explaining methods that accept functions as parameters . 我上周为另一个用户写了一篇很长的文章,你可能会发现它很有用, 解释了接受函数作为参数的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM