Yil*_*ang 2 javascript json d3.js
我正在尝试使用 .json 文件制作散点图。它将让用户选择要显示 json 文件中的哪一组数据。所以我正在尝试使用更新模式。
以下代码将进行第一次绘图,但每次调用 selectGroup() 时(代码在 html 文件中),没有任何更新。console.log(selection) 确实每次都返回一个新数组,但该选择的进入和退出属性始终为空。谁能帮我看看?非常感谢!
var margin = {
top: 30,
right: 40,
bottom: 30,
left: 40
}
var width = 640 - margin.right - margin.left,
height = 360 - margin.top - margin.bottom;
var dataGroup;
var groupNumDefault = "I";
var maxX, maxY;
var svg, xAxis, xScale, yAxis, yScale;
//select and read data by group
function init() {
d3.json("data.json", function (d) {
maxX = d3.max(d, function (d) {
return d.x;
});
maxY = d3.max(d, function (d) {
return d.y;
});
console.log(maxY);
svg = d3.select("svg")
.attr("id", "scatter_plot")
.attr("width", 960)
.attr("height", 500)
.append("g")
.attr("id", "drawing_area")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//x-axis
xScale = d3.scale.linear().range([0, width]).domain([0, maxX]);
xAxis = d3.svg.axis()
.scale(xScale).orient("bottom").ticks(6);
//y-axis
yScale = d3.scale.linear().range([0, height]).domain([maxY, 0]);
yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(6);
svg.append("g")
.attr("class", "x_axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y_axis")
.call(yAxis);
});
selectGroup(groupNumDefault);
}
//update data
function selectGroup(groupNum) {
d3.json("/data.json", function (d) {
dataGroup = d.filter(function (el) {
return el.group == groupNum;
});
console.log(dataGroup);
drawChart(dataGroup);
});
}
//drawing function
function drawChart(data) {
var selection = d3.select("svg").selectAll("circle")
.data(data);
console.log(selection);
selection.enter()
.append("circle")
.attr("class", "dots")
.attr("cx", function (d) {
console.log("updating!");
return xScale(d.x);
})
.attr("cy", function (d) {
return yScale(d.y);
})
.attr("r", function (d) {
return 10;
})
.attr("fill", "red");
selection.exit().remove();
}
init();
Run Code Online (Sandbox Code Playgroud)
这里的问题有两个方面:
首先,您的data()调用中缺少键函数意味着默认情况下数据按索引(数据数组中的位置)匹配,这意味着如果发送到的旧数据集和当前数据集data()大小相同,则没有进入和退出选择。相反,当 d3 按索引匹配时,大部分(可能全部)数据将被放入更新选择中(旧数据集中的第一个数据 = 新数据集中的第一个数据,旧数据集中的第二个数据 = 新数据集中的第二个数据等)
var selection = d3.select("svg").selectAll("circle")
.data(data);
Run Code Online (Sandbox Code Playgroud)
参见:https : //bl.ocks.org/mbostock/3808221
基本上,您需要将您的数据调用调整为这样的内容(如果您的数据具有 .id 属性或任何其他可以唯一标识每个数据的内容)
var selection = d3.select("svg").selectAll("circle")
.data(data, function(d) { return d.id; });
Run Code Online (Sandbox Code Playgroud)
这将根据数据的实际内容而不仅仅是它们的索引生成 enter() 和 exit() (和更新)选择。
其次,并非所有第二轮都保证在进入或退出选择中。某些数据可能只是现有数据的更新,而不是这些选择中的任何一个(在您的情况下,它可能每次都是全新的)。但是,鉴于上面刚刚描述的情况,几乎可以保证您的大部分数据都在更新选择中,其中一些是错误的。要显示更新,您需要像这样更改代码(我在这里假设 d3 v3,显然 v4 略有不同)
selection.enter()
.append("circle")
.attr("class", "dots")
.attr("r", function (d) {
return 10;
})
.attr("fill", "red");
// this new bit is the update selection (which includes the just added enter selection
// now, the syntax is different in v4)
selection // v3 version
// .merge(selection) // v4 version (remove semi-colon off preceding enter statement)
.attr("cx", function (d) {
console.log("updating!");
return xScale(d.x);
})
.attr("cy", function (d) {
return yScale(d.y);
})
selection.exit().remove();
Run Code Online (Sandbox Code Playgroud)
这两个更改应该会看到您的可视化工作,除非问题当然像第二次空数据集一样简单,这也可以解释事情:-)