[英]multiple circles / lines using d3.js
我有一个d3.js问题,已经为此苦苦挣扎了一段时间,似乎无法解决。 我相信这很容易,但是缺少一些非常基本的东西。
具体来说,我有以下代码,它为JSON中的第一个条目生成了一行和两个圆圈-我为第一个条目进行了“硬编码”。
现在,我想将JSON文件的第2和第3项添加到图形中,并控制线条和圆圈的颜色,然后概括代码。
通过阅读文档和StackOverflow,似乎正确的方法是使用嵌套,但是我似乎无法使其正常工作?
代码在jsfiddle上的以下URL上,而javascript在下面。
// INPUT
dataset2 =
[
{
movie : "test",
results :
[
{ week: "20130101", revenue: "60"},
{ week: "20130201", revenue: "80"}
]
},
{
movie : "beta",
results :
[
{ week: "20130101", revenue: "40"},
{ week: "20130201", revenue: "50"}
]
},
{
movie : "gamm",
results :
[
{ week: "20130101", revenue: "10"},
{ week: "20130201", revenue: "20"}
]
}
];
console.log("1");
var parseDate = d3.time.format("%Y%m%d").parse;
var lineFunction = d3.svg.line()
.x(function(d) { return xScale(parseDate(String(d.week))); })
.y(function(d) { return yScale(d.revenue); })
.interpolate("linear");
console.log("2");
//SVG Width and height
var w = 750;
var h = 250;
//X SCALE AND AXIS STUFF
//var xMin = 0;
//var xMax = 1000;
var xScale = d3.time.scale()
.domain([parseDate("20130101"),parseDate("20131231")])
.range([0, w]);
console.log(parseDate("20130101"));
console.log("3");
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
console.log("4S");
//Y SCALE AND AXIS STUFF
var yScale = d3.scale.linear()
.domain([0, 100])
.range([h, 0]);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
console.log("4S1");
//CREATE X-AXIS
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - 30) + ")")
.call(xAxis);
//Create Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + 25 + ",0)")
.call(yAxis);
svg.selectAll("circle")
.data(dataset2[0].results)
.enter()
.append("circle")
.attr("cx", function(d) {
// console.log(d[0]);
console.log(parseDate(d.week));
return xScale(parseDate(d.week));
})
.attr("cy", function (d) {
return yScale(d.revenue);
})
.attr("r", 3);
//create line
var lineGraph = svg.append("path")
.attr("d", lineFunction(dataset2[0].results))
.attr("class", "line");
在d3中的两个上下文中出现“嵌套”一词-使用d3.nest
创建嵌套数据数组,并使用嵌套数据创建嵌套选择。
对于嵌套选择,您的数据已经采用了正确的格式-一个对象数组,每个对象都有一个包含各个数据点的子数组。 因此,您不必担心操作数据,只需要直接将数据连接到嵌套d3选择中的元素即可:
我将快速带您了解它,但是以下教程将为将来提供参考:
在您的示例上:您有一个顶级数据结构,该结构是一个电影对象数组,每个电影对象都包含一个每周收入值的子数组。 您需要确定的第一件事是要与每个数据级别关联的元素类型。 您正在为子数组中的数据绘制一条线和一组圆,但是当前没有为顶级数组对象(电影)添加任何内容。 您需要为它们添加一些东西 ,以便嵌套选择起作用,并且它必须包含直线和圆。 在SVG中,几乎总是一个<g>
(分组)元素。
为了有效地为数据数组中的每个对象创建一个<g>
元素-并将数据对象附加到元素上以供将来参考-您创建一个空选择,将数据连接到其中,然后使用enter()
方法数据联接选择的步骤,为与元素不匹配的每个数据对象添加元素。 在这种情况下,由于我们没有任何要启动的元素,因此所有数据对象都将位于enter()
选择中。 但是,更新某些数据时,相同的模式也适用。
var movies = svg //start with your svg selection,
//it will become the parent to the entering <g> elements
.selectAll("g.movie") //select all <g> elements with class "movie"
//that are children of the <svg> element
//contained in the `svg` selection
//this selection will currently be empty
.data( dataset2 ); //join the selection to a data array
//each object in the array will be associated with
//an element in the selection, if those elements exist
//This data-joined selection is now saved as `movies`
movies.enter() //create a selection for the data objects that didn't match elements
.append("g") //add a new <g> element for each data object
.attr("class", "movie") //set it's class to match our selection criteria
//for each movie group, we're going to add *one* line (<path> element),
//and then a create subselection for the circles
.append("path") //add a <path> within *each* new movie <g> element
//the path will *inherit* the data from the <g> element
.attr("class", "line"); //set the class for your CSS
var lineGraph = movies.select("path.line")
//All the entered elements are now available within the movies selection
//(along with any existing elements that we were updating).
//Using select("path") selects the first (and only) path within the group
//regardless of whether we just created it or are updating it.
.attr("d", function(d){ return lineFunction(d.results); });
//the "d" attribute of a path describes its shape;
//the lineFunction creates a "d" definition based on a data array.
//If the data object attached to the path had *only* been the d.results array
//we could have just done .attr("d", lineFunction), since d3
//automatically passes the data object to any function given as the value
//of an .attr(name, value) command. Instead, we needed to create an
//anonymous function to accept the data object and extract the sub-array.
var circles = movies.selectAll("circle")
//there will be multiple circles for each movie group, so we need a
//sub-selection, created with `.selectAll`.
//again, this selection will initially be empty.
.data( function(d) {return d.results; });
//for the circles, we define the data as a function
//The function will be called once for each *movie* element,
//and passed the movie element's data object.
//The resulting array will be assigned to circles within that particular
//movie element (or to an `enter()` selection, if the circles don't exist).
circles.enter() //get the data objects that don't have matching <circle> elements
.append("circle") //create a circle for each
//the circles will be added to the appropriate "g.movie"
//because of the nested selection structure
.attr("r", 3); //the radius doesn't depend on the data,
//so you can set it here, when the circle is created,
//the same as you would set a class.
circles //for attributes that depend on the data, they are set on the entire
//selection (including updating elements), after having created the
//newly entered circles.
.attr("cx", function(d) { return xScale( parseDate(d.week) ); })
.attr("cy", function(d) { return yScale( d.revenue ); });
包含其余代码的实时版本: http : //jsfiddle.net/GVmVk/3/
您将需要调整x比例尺的域,以便不截断第一个数据点,并且需要确定如何使用电影标题属性,但这应该可以帮助您。
是的,的确, 嵌套选择是进行圆的一种方法,尽管路径不需要它们:
svg.selectAll("g.circle")
.data(dataset2)
.enter()
.append("g")
.attr("class", "circle")
.selectAll("circle")
.data(function(d) { return d.results; })
.enter()
.append("circle")
.attr("cx", function(d) {
// console.log(d[0]);
console.log(parseDate(d.week));
return xScale(parseDate(d.week));
})
.attr("cy", function (d) {
return yScale(d.revenue);
})
.attr("r", 3);
//create line
var lineGraph = svg.selectAll("path.line")
.data(dataset2).enter().append("path")
.attr("d", function(d) { return lineFunction(d.results); })
.attr("class", "line");
这里完整的例子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.