#javascript #d3.js
Вопрос:
Я думал, что это должно быть просто, но у меня возникли проблемы. Я пытаюсь отфильтровать набор данных на основе переменной, выбранной в раскрывающемся списке, и обновить диаграмму в d3. Раскрывающийся список заполняется, и начальная диаграмма отображается нормально, но не обновляется, когда я изменяю раскрывающийся список.
Примеры данных:
Year,VarA,VarB,VarC,VarD
1984,34,56,90,X
1984,69,38,58,Y
1988,50,35,28,X
Соответствующий код:
// Create a dropdown
var yearMenu = d3.select("#yearDropdown")
yearMenu
.append("select")
.selectAll("option")
.data(nest)
.enter()
.append("option")
.attr("value", ([key, ]) => key)
.text(([key, ]) => key)
// Circles
var circles = svg.selectAll('circle')
.data(data.filter(d => d.Year == "1984"))
.enter()
.append('circle')
.attr('cx', d => xScale(d.VarA))
.attr('cy', d => yScale(d.VarB))
.attr('r', d => rScale(d.VarC)/rDivisor)
.attr('stroke', 'black')
.attr('stroke-width',2)
.style('fill', 'white')
.attr('class', 'points')
var updateGraph = function(selectedYear) {
var dataFilter = data.filter(d => d.Year == selectedYear)
circles.data(dataFilter)
.selectAll("circle.points")
.transition()
.duration(1000)
.attr('cx', d => xScale(d.VarA))
.attr('cy', d => yScale(d.VarB))
.attr('r', d => rScale(d.VarC)/rDivisor)
}
// When the button is changed, run the updateChart function
yearMenu.on("change", function() {
// recover the option that has been chosen
var selectedOption = d3.select(this)
.select("select")
.property("value")
// run the updateChart function with this selected option
updateGraph(selectedOption)
});
Ответ №1:
Вот пример:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<body>
<div id="yearDropdown"></div>
<div id="chart"></div>
<script>
// set up
const width = 200;
const height = 200;
const svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height);
// data
const data = [
{ Year: '1984', VarA: 34, VarB: 56, VarC: 90, VarD: 'X' },
{ Year: '1984', VarA: 69, VarB: 38, VarC: 58, VarD: 'Y' },
{ Year: '1988', VarA: 50, VarB: 35, VarC: 28, VarD: 'X' }
];
// scales
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, 100])
.range([height, 0]);
const rScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 20]);
// circles
let circles = svg.selectAll('circle');
function drawCircles(year) {
circles = circles
.data(data.filter(d => d.Year === year))
.join('circle')
.attr('stroke', 'black')
.attr('stroke-width', 2)
.style('fill', 'white');
circles
.transition()
.duration(1000)
.attr('cx', d => xScale(d.VarA))
.attr('cy', d => yScale(d.VarB))
.attr('r', d => rScale(d.VarC));
}
// select menu
const yearMenu = d3.select('#yearDropdown')
.append('select');
yearMenu.selectAll('option')
.data(['1984', '1988'])
.join('option')
.attr('value', d => d)
.text(d => d);
yearMenu.on('change', function(event) {
drawCircles(event.target.value);
});
// draw the inital circles
drawCircles(yearMenu.property('value'));
</script>
</body>
</html>
yearMenu
должно быть меню выбора, а не div, содержащий его. Кроме того, функция, которая обновляет диаграмму, должна обрабатывать, когда новые данные содержат другое количество элементов, чем предыдущие данные.