I was making an animated scatter plot with dropdown to select group. The dataset I’m using is Biden’s 2022 satisfaction rate. However, I couldn’t make it works properly, as the video shows. I tried for a long time but still failed to figure the reasons out. My codes are below. Great appreciation if someone could help me. Thank you!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>D3 Assignment</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<select id="selectButton"></select>
<div id="BidenSatisfaction"></div>
</head>
<script>
const margin = {top: 10, right: 100, bottom: 30, left: 30},
width = 1500 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
const svg = d3.select("#BidenSatisfaction")
.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})`);
d3.csv("approval_topline.csv").then(function(data){
const allGroup = ["Approve", "Disapprove"]
d3.select("#selectButton")
.selectAll('myOptions')
.data(allGroup)
.enter()
.append('option')
.text(d => d)
.attr("value", d => d)
const x = d3.scaleTime()
.domain(d3.extent(data, function(d) {
return new Date(d.Date);
}))
.range([15, width]);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
const y = d3.scaleLinear()
.domain( [30,60])
.range([ height, 20 ]);
svg.append("g")
.call(d3.axisLeft(y));
const line = svg.append('g')
.append("path")
.datum(data)
.attr("d", d3.line()
.x(d => x(+new Date(d.Date)))
.y(d => y(+d.Approve))
)
.attr("stroke", "grey")
.style("stroke-width", 3)
.style("fill", "none")
const dot = svg.selectAll('circle')
.data(data)
.join('circle')
.attr("cx", d => x(+new Date(d.Date)))
.attr("cy", d => y(+d.Approve))
.attr("r", 5)
.style("fill", "#69b3a2")
function update(selectedGroup){
const dataFilter = data.map(function(d){return {date:Date(d.Date), value:d[selectedGroup]} })
line.datum(dataFilter)
.transition()
.duration(1000)
.attr("d", d3.line()
.x(d => x(+new Date(d.Date)))
.y(d => y(+d.value))
)
dot.data(dataFilter)
.transition()
.duration(1000)
.attr("cx", d => x(+new Date(d.Date)))
.attr("cy", d => y(+d.value))
}
d3.select("#selectButton").on("change", function(event, d) {
let selectedOption = d3.select(this).property("value")
update(selectedOption)})
})
</script>
</html>