我试图使用.json文件制作散点图。它将允许用户选择要显示的json文件中的哪组数据。所以我试图使用更新模式。
以下代码将进行第一次绘制,但每次调用selectGroup()(代码都在html文件中)时,都没有更新。 console.log(选择)每次都返回一个新数组,但该选择的enter和exit属性始终为空。 任何人都可以帮我看看吗?非常感谢!
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();
答案 0 :(得分:2)
这里的问题有两个方面:
首先,您在data()
调用中缺少关键函数意味着默认情况下数据与索引(数据数组中的位置)匹配,这意味着如果发送旧数据集和当前数据集,则不会进入和退出选择data()
大小相同。相反,当d3与索引匹配时,大多数(可能全部)数据将被放入 update 选择中(旧数据集中的第一个数据=新数据集中的第一个数据,旧数据集中的第二个数据=第二个数据)在新的数据集等))
var selection = d3.select("svg").selectAll("circle")
.data(data);
请参阅:https://bl.ocks.org/mbostock/3808221
基本上,您需要将数据调用调整为这样的(如果您的数据具有.id属性或其他任何可以唯一标识每个数据的内容)
var selection = d3.select("svg").selectAll("circle")
.data(data, function(d) { return d.id; });
这将根据数据的实际内容生成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();
这两个更改应该看到您的可视化工作正常,除非问题是第二次这样简单的空数据集,这也可以解释: - )