将d3条形图重置为原始数据源时,重复轴节点
Duplicate axis nodes when resetting d3 bar chart to original data source
我有一个交互式d3条形图(条形图是可拖动的)和一个相关的HTML表,让我了解正在绘制的底层数据。我有一个"重置"按钮,它应该在用户玩过图表数据后将其重置为原始状态。我不明白的是,为什么HTML表正确重置,而图表却没有。我认为这与我对d3的enter()/update()的误解有关,但据我所知,这就是我的理解
完整演示位于http://jsfiddle.net/HHLrF/但这是相关代码:
d3.json("data/tax_stacked.json", function(error, data) {
var mydata = clone(data); // Use a copy of the data to store user's preference.
var desc = function (a,b) { return d3.descending(+a.value, +b.value);}
mydata.sort(desc);
x.domain([0, d3.max(mydata, function(d) { return +d.value * 1.1; })]);
y.domain(mydata.map(function(d) { return d.name; }));
var defs = chart.insert("defs",".tax");
drawchart();
d3.select("button").on("click",function () {
mydata = clone(data);
mydata.sort(desc);
drawchart();
});
function drawtable() {
console.log("drawing table...");
var columns = ["name", "value"];
var table = d3.select("#grid");
table.html("");
var thead = table.append("thead"),
tbody = table.append("tbody");
// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) { return column; });
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(mydata)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.text(function(d) { return d.value; });
}
function drawchart() {
var drag = d3.behavior.drag()
.on("dragstart", function(){
var where;
d3.select(this).classed({"bar": true, "moved": true});
})
.on("drag", function(d){
where = d3.event.x;
d3.select(this)
.attr("width", where);
d3.select(this.nextSibling) // Move the label
.attr("x", where + 10);
/* Some lines omitted here for brevity */
d.value = parseInt(x.invert(where));
drawtable();
})
.on("dragend", function(d){
});
var taxes = chart.selectAll(".tax")
.data(mydata)
.enter()
.append("g")
.classed("tax", true);
// Clipping paths to swap colours when the user's figures exceed original figures (work in progress!)
defs.selectAll(".cp")
.data(mydata)
.enter()
.append("clipPath")
.attr("id", function (d,i) { return "cp" + i; })
.append("rect")
.attr("x", function(d) { return x(d.value); })
.attr("y", function(d) { return y(d.name); })
.attr("width", function(d) { return width - x(d.value); })
.attr("height", y.rangeBand());
// Light blue bars for the original budget figures
taxes.append("rect")
.classed("original", true)
.attr("x", function(d) { return x(0); })
.attr("y", function(d) { return y(d.name); })
.attr("width", function(d) { return x(d.value); })
.attr("height", y.rangeBand())
.attr("rx",0);
// Medium blue bars for the user's budget figures
taxes.append("rect")
.attr("class", function (d) { return (d.fixed == "y") ? "fixed" : "bar"; })
.attr("x", function(d) { return x(0); })
.attr("y", function(d) { return y(d.name)+1; })
.attr("width", function(d) { return x(d.value); })
.attr("height", y.rangeBand()-1)
.attr("rx",0)
.attr("title", function (d) { return d.value; })
.attr("clipper", function (d,i) { return "url(#cp" + i + ")"; });
// .attr("clip-path", function (d,i) { return "url(#cp" + i + ")"; });
taxes.append("text")
.attr("class", "label")
.attr("x", function(d) { return x(d.value)+10; })
.attr("y", function(d) { return y(d.name); })
.attr("dy", "1.6em")
.text( function (d) { return d.name; });
var iconptr = taxes.append("g")
.classed("smooth", true)
.attr("transform", function (d) {
return "translate(" + (x(d.value)+labelpadding+parseInt(this.previousSibling.getBBox().width)) + "," + (y(d.name)+7) + ") scale(0.037,0.037)";
});
/* Some lines omitted here for brevity */
// Draw the axes
chart.append("g")
.attr("class", "x axis")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
d3.selectAll(".bar").call(drag);
drawtable();
}
});
当前实现中存在以下几个问题:
- 每次单击重置按钮时都会附加两个轴
- 单击"重置"按钮后,图表不会更新
- 单击"重置"按钮后,表更新不起作用
有很多话可以说,但集中在几个要点上,你的图表没有更新,因为正如你所怀疑的,输入/更新选择没有得到正确处理。您可以在输入选择之外执行所有操作,并且由于您没有为数据设置关键帧(例如按值),也没有添加/删除元素,因此在启动时构建图表后,输入选择中不会有任何内容。我已经解决了这个问题,并在适当的地方发表了评论。
我还修复了轴的重复,并在用户播放图表并单击重命名的Redraw按钮后适当地刷新它们。我为什么要重命名按钮?基本上,您使用的克隆技术并没有真正起作用。您可以对此进行进一步调查,但为了方便起见,我删除了对克隆数据的所有提及,只对原始数据进行了操作。因此,不,原始数据没有被重新设置,但当用户与图形交互时,以下数据正在工作:
- 表格更新工作(包括排序)
- 图表更新工作(包括排序)
-
x轴更新并反映新的数据幅度
// preserve the enter selection in a variable for re-use!!! var taxesEnter = taxes .enter() .append("g") .classed("tax", true);
使用修复程序完成FIDDLE。
因此,这不是你想要的重新设置(再次调查克隆情况),但它有各种有用的部分可以掌握。在这种程度上,我希望它对你有用。
万岁!由于对"update"和enter()有了更好的理解,它现在可以工作了。更新后的Fiddlehttp://jsfiddle.net/HHLrF/3/或阅读以下内容。除了@FernOfTheAndes的帮助,我发现http://bl.ocks.org/mbostock/3808218有用的
d3.json("data/tax_stacked.json", function(error, data) {
var mydata = clone(data); // Use a copy of the data to store user's preference.
var desc = function (a,b) { return d3.descending(+a.value, +b.value);}
mydata.sort(desc);
x.domain([0, d3.max(mydata, function(d) { return +d.value * 1.1; })]);
y.domain(mydata.map(function(d) { return d.name; }));
var defs = chart.append("defs");
// Draw the axes
chart.append("g")
.attr("class", "x axis");
chart.append("g")
.attr("class", "y axis");
drawchart();
drawtable();
d3.select("button").on("click",function () {
mydata = clone(data);
mydata.sort(desc);
d3.selectAll("rect.bar")
.data(mydata) // We're rebinding at this level rather than taxes level because the reset value is not propagating down to the <rect class="bar moved"> by itself.
.attr("width", function(d) { console.log(x(d.value)); return x(d.value); });
drawtable();
});
function drawtable() {
// From http://stackoverflow.com/questions/9268645/creating-a-table-linked-to-a-csv-file
var columns = ["name", "value"];
var table = d3.select("#grid");
table.html("");
var thead = table.append("thead"),
tbody = table.append("tbody");
// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) { return column; });
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(mydata)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.text(function(d) { return d.value; });
}
function drawchart() {
var drag = d3.behavior.drag()
.on("dragstart", function(){
var where;
d3.select(this).classed({"bar": true, "moved": true});
})
.on("drag", function(d){
where = d3.event.x;
d3.select(this)
.attr("width", where);
d.value = "" + parseInt(x.invert(where));
drawtable();
})
.on("dragend", function(d){
});
var taxes = chart.selectAll(".tax")
.data(mydata);
var taxenter = taxes.enter()
.append("g")
.classed("tax", true);
// Light blue bars for the original budget figures
taxenter.append("rect")
.classed("original", true)
.attr("x", function(d) { return x(0); })
.attr("y", function(d) { return y(d.name); })
.attr("width", function(d) { return x(d.value); })
.attr("height", y.rangeBand())
.attr("rx",0);
// Medium blue bars for the user's budget figures
taxenter.append("rect")
.attr("class", function (d) { return (d.fixed == "y") ? "fixed" : "bar"; })
.attr("x", function(d) { return x(0); })
.attr("y", function(d) { return y(d.name)+1; })
.attr("width", function(d) { return x(d.value); })
.attr("height", y.rangeBand()-1)
.attr("rx",0)
.attr("title", function (d) { return d.value; });
// Draw the axes
chart.selectAll(".x")
.call(xAxis);
chart.select(".y")
.call(yAxis);
// Enable dragging
d3.selectAll(".bar").call(drag);
}
});
- 节点导出返回一个空对象
- 可以前端maven插件使用节点,npm已经安装
- 在jstree中,如何将指定的节点集中到大型树上
- 节点Js:How to catch a“;没有这样的文件或目录“;读取线模块出错
- 如何从模块链中调用函数.导出到节点中
- 节点是否需要模块传递带有方括号的arg?这是个错误吗
- d3基于用户选择动态更新节点
- 有条件更新d3.js力图中节点的最佳方法
- Datatables:通过DOM数据源中的名称引用列
- 如何处理node.js节点mongodb中的连接和查询队列
- 将DOM节点值与字符串Javascript进行比较
- 节点fs.stat名称未定义
- 无法安装节点sass相关性
- 节点协同与生成器和Promise并行流量控制
- 节点.js将变量显示为 HTML
- 如何将JSON数据源适合Jquery自动完成小部件
- 将节点数据分配给另一个变量jstree
- 如何在动态创建的节点上绑定函数
- 承诺在非节点式回调上使用Bluebird
- 将d3条形图重置为原始数据源时,重复轴节点