chart2_stephen = () => {
const width = 1100, height = 800, margin = { top: 80, right: 50, bottom: 120, left: 50 };
const filteredData = showAllYears ? spotify_data :
spotify_data.filter(d => new Date(d.track_album_release_date).getFullYear() === selectedYear);
const sortedData = [...filteredData].sort((a, b) => a.danceability - b.danceability);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const xScale = d3.scaleLinear()
.domain([0, d3.max(spotify_data, d => d.danceability)])
.range([0, width - margin.left - margin.right - 30]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(spotify_data, d => d.track_popularity)])
.range([height - margin.top - margin.bottom, 0]);
const rScale = d3.scaleSqrt()
.domain(d3.extent(sortedData, d => d.valence))
.range([5, 20]);
const colorScale = d3.scaleOrdinal()
.domain([...spotify_data].map(d => d.playlist_genre))
.range([
"#ff6f4b",
"#F06292",
"#D81B60",
"#FFB343",
"#9C1C6C",
"#6A1B9A",
"#4A148C",
"#290E7D",
]);
g.append("g")
.attr("transform", `translate(0, ${height - margin.top - margin.bottom})`)
.call(d3.axisBottom(xScale));
g.append("g")
.call(d3.axisLeft(yScale));
g.selectAll("circle")
.data(sortedData)
.enter().append("circle")
.attr("cx", d => xScale(d.danceability) + 8)
.attr("cy", d => yScale(d.track_popularity) - 18)
.attr("r", d => rScale(d.valence))
.attr("fill", d => colorScale(d.playlist_genre))
.attr("opacity", 0.8)
.on("mouseover", (event, d) => {
d3.select("#tooltip")
.style("left", `${tooltipX(xScale(d.danceability) + 8)}px`)
.style("top", `${tooltipY(yScale(d.track_popularity) - 18, event.pageY)}px`)
.style("width", '300px')
.style("height",'350px')
.style("display", "block")
.html(`
<strong>${d.track_name}</strong> by ${d.track_artist}<br>
Genre: ${d.playlist_genre}<br>
Danceability: ${d.danceability.toFixed(2)}<br>
Energy: ${d.energy.toFixed(2)}<br>
Popularity: ${d.track_popularity.toFixed(2)}<br>
Valence: ${d.valence.toFixed(2)}<br>
Tempo: ${d.tempo.toFixed(2)}<br>
<img src="${d.image_url}" alt="${d.track_name}" style="max-width: 100px; height: auto; display: block; margin: 10px auto;">
<iframe src="https://open.spotify.com/embed/track/${d.spotify_url.split('/').pop()}" width="300" height="80" frameborder="0" allowtransparency="true" allow="encrypted-media"></iframe>
`);
})
.on("mouseout", () => d3.select("#tooltip").style("display", "none"));
if (d3.select("#tooltip").empty()) {
d3.select("body").append("div")
.attr("id", "tooltip")
.style("position", "absolute")
.style("background", "white")
.style("padding", "5px")
.style("border", "1px solid black")
.style("display", "none");
}
svg.append("text")
.attr("x", width / 2)
.attr("y", margin.top / 2.5)
.attr("text-anchor", "middle")
.attr("font-size", "18px")
.attr("font-weight", "bold")
// show the currently selected Year at the top of the graph for clarity, feel free to remove if too much
.text(`Mapping Danceability and Popularity by Genre of Spotify Tracks ${
showAllYears ? " - 1965 to 2020" : " - "+selectedYear}`);
svg.append("text")
.attr("x", width / 2)
.attr("y", height - margin.bottom + 40)
.attr("text-anchor", "middle")
.attr("font-size", "14px")
.text("Danceability");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -height / 2)
.attr("y", margin.left - 40)
.attr("text-anchor", "middle")
.attr("font-size", "14px")
.text("Popularity");
// adding the legend to the right hand side
const legend = svg.append("g")
.attr("transform", `translate(${width - margin.right - 15}, ${margin.top})`);
// grab the unique genres
const genres = [...new Set(spotify_data.map(d => d.playlist_genre))];
// create the item to store the colored rectangle and genre text
const legendItem = legend.selectAll(".legend-item")
.data(genres)
.enter().append("g")
.attr("class", "legend-item")
.attr("transform", (d, i) => `translate(0, ${i * 25})`);
legendItem.append("rect")
.attr("width", 20)
.attr("height", 20)
.attr("fill", d => colorScale(d));
legendItem.append("text")
.attr("x", 30)
.attr("y", 15)
.attr("font-size", "14px")
.text(d => d);
return svg.node();
}