有几种方法可以只使用 D3 来做您想做的事情,而无需任何其他库并且无需更改数据。其中之一是使用groups 处理“更高”级别的数据(关于嵌套数据)。让我们在这段代码中看到它:
首先,我模拟了一个和你一样的数据集:
var data = [
{name: "male",
values: [{ x: 123,y: 234},
{ x: 432,y: 221},
{ x: 199,y: 56}]
},
{name: "female",
values: [{ x: 223,y: 111},
{ x: 67,y: 288},
{ x: 19, y: 387}]
}
];
这是我们要使用的数据。我将在这里制作一个散点图(仅作为示例),所以,让我们为访问第二级数据的尺度设置域(x 和y 内values):
var xScale = d3.scaleLinear().range([20, 380])
.domain([0, d3.max(data, function(d){
return d3.max(d.values, function(d){
return d.x;
})
})]);
var yScale = d3.scaleLinear().range([20, 380])
.domain([0, d3.max(data, function(d){
return d3.max(d.values, function(d){
return d.y;
})
})]);
现在最重要的部分来了:我们要将数据绑定到“组”,而不是圆形元素:
var circlesGroups = svg.selectAll(".circlesGroups")
.data(data)
.enter()
.append("g")
.attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"});
一旦在第一级数据中我们有 2 个对象,D3 将为我们创建 2 个组。
我也用group来设置圈子的颜色:如果name是“男”,圈子是蓝色的,否则是红色的:
.attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"});
现在,随着组的创建,我们根据每个组的数据中的values创建圆圈,数据绑定如下:
var circles = circlesGroups.selectAll(".circles")
.data(function(d){ return d.values})
.enter()
.append("circle");
这里function(d){ return d.values}会根据values数组中的对象将数据绑定到圆上。
然后你定位你的圈子。这是全部代码,点击“运行代码sn-p”查看:
var data = [
{name: "male",
values: [{ x: 123,y: 234},
{ x: 432,y: 221},
{ x: 199,y: 56}]
},
{name: "female",
values: [{ x: 223,y: 111},
{ x: 67,y: 288},
{ x: 19, y: 387}]
}
];
var xScale = d3.scaleLinear().range([20, 380])
.domain([0, d3.max(data, function(d){
return d3.max(d.values, function(d){
return d.x;
})
})]);
var yScale = d3.scaleLinear().range([20, 380])
.domain([0, d3.max(data, function(d){
return d3.max(d.values, function(d){
return d.y;
})
})]);
var xAxis = d3.axisBottom(xScale).tickSizeInner(-360);
var yAxis = d3.axisLeft(yScale).tickSizeInner(-360);
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 400);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,380)")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(20,0)")
.call(yAxis);
var circlesGroups = svg.selectAll(".circlesGroups")
.data(data)
.enter()
.append("g")
.attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"});
var circles = circlesGroups.selectAll(".circles")
.data(function(d){ return d.values})
.enter()
.append("circle");
circles.attr("r", 10)
.attr("cx", function(d){ return xScale(d.x)})
.attr("cy", function(d){ return yScale(d.y)});
.axis path, line{
stroke: gainsboro;
}
<script src="https://d3js.org/d3.v4.min.js"></script>