#d3.js
#d3.js
Вопрос:
Я делаю визуальный проект, чтобы показать стихийное бедствие в 1900-2018 годах, используя d3. Я хочу добавить интерактивное действие, которое можно выбрать для отображения первого и последнего года.
Первоначально я создаю изображение следующим образом:
d3.csv("output.csv", rowConventer, function (data) {
dataset = data;
var xScale = d3.scaleBand()
.domain(d3.range(dataset.length))
.range([padding, width - padding])
.paddingInner(0.05);
var yScale = d3.scaleLinear()
.domain([0,
d3.max(dataset, function (d) {
return d.AllNaturalDisasters;
})])
.range([height - padding, padding])
.nice();
stack = d3.stack().keys(["Drought", "Earthquake", "ExtremeTemperature", "ExtremeWeather", "Flood", "Impact", "Landslide", "MassMovementDry", "VolcanicActivity", "Wildfire"]);
series = stack(dataset);
gr = svg.append("g");
groups = gr.selectAll("g")
.data(series)
.enter()
.append("g")
.style("fill", function(d, i) {
return colors(i);
})
.attr("class", "groups");
rects = groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return yScale(d[1]);
})
.attr("height", function(d) {
return yScale(d[0]) - yScale(d[1]);
})
.attr("width", xScale.bandwidth())
.append("title")
.text(function (d) {
var rect = this.parentNode;// the rectangle, parent of the title
var g = rect.parentNode;// the g, parent of the rect.
return d.data.Year ", " d3.select(g).datum().key "," (d[1]-d[0]);
});
d3.select("button")
.on("click", choosePeriod);
Я упростил некоторый код, чтобы упростить свой вопрос. В последней строке я добавляю прослушиватель событий для достижения того, что я описал выше. И функция обновления — choosePeriod. Теперь это выглядит следующим образом:
function choosePeriod() {
firstYear = parseInt(document.getElementById("FirstYear").value);
lastYear = parseInt(document.getElementById("LastYear").value);
d3.csv("output.csv", rowConventer, function (newdata) {
dataset = newdata;
series=stack(dataset);
groups.data(series);
groups.selectAll("rect")
.data(function (d) {
return d;
})
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScales(i);
})
.attr("y", function(d) {
return yScales(d[1]);
})
.attr("height", function(d) {
return yScales(d[0]) - yScales(d[1]);
})
.attr("width", xScales.bandwidth())
.append("title")
.text(function (d) {
var rect = this.parentNode;// the rectangle, parent of the title
var g = rect.parentNode;// the g, parent of the rect.
return d.data.Year ", " d3.select(g).datum().key "," (d[1]-d[0]);
});
groups.selectAll("rect")
.data(function (d) {
return d;
})
.exit()
.remove();
})
}
Изменение набора данных достигается с помощью rowConventer
, что не важно в этом вопросе. Теперь функция choosePeriod
работает не так, как предполагалось! enter
И exit
и update
все работают неправильно! Вся картина в беспорядке! Я хочу, например, чтобы, если я ввожу firstYear=1900
и lastYear=2000
, то изображение должно быть обновлено с отображением периода 1900-2000. Как я могу этого добиться?
Я незнаком с расположением всей структуры, я имею в виду, что в каком-то месте использование d3.select()
by class
или id
вместо label
лучше, верно?
Ответ №1:
Похоже, вы разобрались с выборками ввода и выхода. Единственное, чего вам не хватает, — это выбор обновления, который будет иметь дело с прямоугольниками, которые уже существуют и не нуждаются в добавлении или удалении. Для этого скопируйте шаблон обновления, но просто удалите бит enter().append(), например:
groups.selectAll("rect")
.data(function (d) {
return d;
})
.attr("x", function(d, i) {
return xScales(i);
})
.attr("y", function(d) {
return yScales(d[1]);
})
.attr("height", function(d) {
return yScales(d[0]) - yScales(d[1]);
})
.attr("width", xScales.bandwidth())
.append("title")
.text(function (d) {
var rect = this.parentNode;// the rectangle, parent of the title
var g = rect.parentNode;// the g, parent of the rect.
return d.data.Year ", " d3.select(g).datum().key "," (d[1]-d[0]);
})
Комментарии:
1. на самом деле, enter (), exit(), update () работают некорректно. И это то, что меня озадачивает. Спасибо и извините, что забыли сказать это в первый раз!
2.Подождите!! Извините, что не попробовал ваш метод десять часов назад, я попробовал это только сейчас
update
enter
, используя последовательностьexit
and, и она работает правильно!