Pensé que esto debería ser sencillo, pero estoy teniendo problemas. Estoy tratando de filtrar un conjunto de datos basado en una variable seleccionada en un menú desplegable y hacer que el gráfico se actualice en d3. El menú desplegable se completa y el gráfico inicial se muestra bien, pero no se actualizará cuando cambie el menú desplegable.
Data de muestra:
Year,VarA,VarB,VarC,VarD 1984,34,56,90,X 1984,69,38,58,Y 1988,50,35,28,XCódigo relevante:
// 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) });Aquí hay un ejemplo:
<!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 debe ser el menú de selección, no el div que lo contiene. Además, la función que actualiza el gráfico debe manejar cuando los nuevos datos tienen una cantidad diferente de elementos que los datos anteriores.