更新D3图表,导致重复图表 [英] Updating D3 chart resulting in duplicate charts
问题描述
我有一个时间试图更新JSON数据到按钮点击后D3直方图的时间。
I am having a hell of a time trying to update JSON data going to a D3 histogram after a button click.
当我解决了按钮点击更新问题,D3 javascript现在每个按钮点击附加一个图表,从而产生重复的图表而不是简单地更新数据。
While I solved the button click to update issue, the D3 javascript is now appending one chart per button click, resulting in duplicate charts instead of simply updating the data.
我理解点击事件调用 append()
在D3代码中每次触发,但是如何解决这个问题,所以只有一个图表更新的数据每次点击?
I understand that the click event is calling append()
in the D3 code every time it is triggered, but how can I get around this so there's only one chart with updated data per click?
console.log('chart.js loaded');
$(document).ready(function() {
var vimeoVideoId = $('p#vimeoVideoId').text();
var api = 'http://localhost:3001/videos/' + vimeoVideoId + '/json';
function initData() {
$('#all-notes').click(function() {
getData();
});
}
function getData() {
$.getJSON(api, draw);
}
function draw(json) {
data = json;
var duration = data.duration;
var timeToSec = function(data) {
notes = [];
// convert min:sec to seconds
for(i=0; i < data.notes.length; i++) {
var min_sec = data.notes[i].timecode;
var tt = min_sec.split(':');
var seconds = tt[0]*60+tt[1]*1;
notes.push(seconds);
}
return notes;
};
noteTimes = timeToSec(data);
console.log(noteTimes);
// Formatters for counts and times (converting numbers to Dates).
var formatCount = d3.format(",.0f"),
formatTime = d3.time.format("%H:%M"),
formatMinutes = function(d) { return formatTime(new Date(2012, 0, 1, 0, d)); };
var margin = {top: 10, right: 20, bottom: 30, left: 20},
width = 550;
height = 285;
var x = d3.scale.linear()
.domain([0, duration])
// .domain([0, d3.max(noteTimes)])
.range([0, width]);
// Generate a histogram using twenty uniformly-spaced bins.
var data = d3.layout.histogram()
.bins(x.ticks(50))
(noteTimes);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.y; })])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(formatMinutes);
var svg = d3.select("#chartSet").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var bar = svg.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });
bar.append("rect")
.attr("x", 1)
.attr("width", x(data[0].dx) - 1)
.attr("height", function(d) { return height - y(d.y); });
bar.append("text")
.attr("dy", ".75em")
.attr("y", 6)
.attr("x", x(data[0].dx) / 2)
.attr("text-anchor", "middle")
.text(function(d) { return formatCount(d.y); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
}
initData();
});
推荐答案
要处理创建和更新,如何写 draw
函数。
To handle creation and updates, you will have to reorganize how the draw
function is written.
function draw(json) {
// Initialization (few wasted CPU cycles)
// ...
// Update hook
var svg = d3.select("#chartSet").data([data]);
// Enter hook
var svgEnter = svg.enter();
// Enter cycle
svgEnter.append("svg")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Update cycle
svg
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// Exit cycle (not really needed here)
svg.exit().remove();
// Update hook
var bar = svg.selectAll(".bar")
.data(data)
// Enter hook
var barEnter = bar.enter();
// Enter cycle
var barG_Enter = barEnter
.append("g")
.attr("class", "bar")
barG_Enter
.append("rect")
.attr("x", 1);
barG_Enter
.append("text")
.attr("dy", ".75em")
.attr("y", 6)
.attr("text-anchor", "middle");
// Update cycle
bar.attr("transform", function(d) {
return "translate(" + x(d.x) + "," + y(d.y) + ")"; });
bar.select("rect")
.attr("width", x(data[0].dx) - 1)
.attr("height", function(d) { return height - y(d.y); });
bar.select("text")
.attr("x", x(data[0].dx) / 2)
.text(function(d) { return formatCount(d.y); });
// Exit cycle
bar.exit().remove();
// Enter cycle
svgEnter.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Update cycle
svg.select('g.x.axis')
.call(xAxis);
}
此 classic enter-update-exit 模式在这篇有关制作可重复使用的文章图表。这个答案很大程度上取决于这种模式。
This classical enter-update-exit pattern is improved upon in this article on making reusable graphs. This answer draws heavily on that pattern.
使用closures的一个更好的实现,你将能够节省每次浪费在初始化上的几个CPU周期。
With a slightly better implementation which uses closures, you will be able to save the few CPU cycles wasted on initialization each time.
这篇关于更新D3图表,导致重复图表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!