有几种方法你只想使用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}]
}
];
这是数据我们要去使用。我要让散点图这里(只是作为一个例子),所以,让我们设置的域访问数据的(内部values
x
和y
)第二级的尺度:
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组给我们。
我还使用了组设置圆的颜色:如果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
阵列内的对象的数据绑定到的社交圈。
然后你定位你的圈子。这是整个代码,点击“运行代码片断”可以看到:
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])
\t .domain([0, d3.max(data, function(d){
\t \t \t return d3.max(d.values, function(d){
\t \t \t \t return d.x;
\t \t })
\t })]);
\t \t
var yScale = d3.scaleLinear().range([20, 380])
.domain([0, d3.max(data, function(d){
\t \t \t return d3.max(d.values, function(d){
\t \t \t \t return d.y;
\t \t })
\t })]);
var xAxis = d3.axisBottom(xScale).tickSizeInner(-360);
var yAxis = d3.axisLeft(yScale).tickSizeInner(-360);
var svg = d3.select("body")
\t .append("svg")
\t .attr("width", 400)
\t .attr("height", 400);
svg.append("g")
\t .attr("class", "x axis")
\t .attr("transform", "translate(0,380)")
\t .call(xAxis);
\t
svg.append("g")
\t .attr("class", "y axis")
\t .attr("transform", "translate(20,0)")
\t .call(yAxis);
\t
var circlesGroups = svg.selectAll(".circlesGroups")
\t .data(data)
\t .enter()
\t .append("g")
\t .attr("fill", function(d){ return (d.name == "male") ? "blue" : "red"});
\t
var circles = circlesGroups.selectAll(".circles")
\t .data(function(d){ return d.values})
\t .enter()
\t .append("circle");
\t \t
circles.attr("r", 10)
\t .attr("cx", function(d){ return xScale(d.x)})
\t .attr("cy", function(d){ return yScale(d.y)});
.axis path, line{
\t stroke: gainsboro;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
感谢,它的工作原理,但有可能只用纯JS或D3做到这一点不改变数据?我想提高我的技能:) – Shawn
@shawn当然可以。 Underscore.js是开源的,你可以检查事情是如何完成的。这并不难理解。代码在这里:http://underscorejs.org/underscore.js 你不能轻易地做到这一点与D3没有改变数据......有一种方法,但它没有优化。你quand做一个foreach数据,然后做焦点。选择所有值,并以这种方式追加你的圈子。 – rm4