chart_2 = {
const width = 1000;
const height = 600;
const marginRight = 20;
const marginLeft = 20;
const marginBottom = 20;
const popScale = 2;
const radius = 16;
const padding = 7;
const x = d3
.scaleLinear()
.domain(d3.extent(alone, (d) => d["days_lasted"]))
.range([marginLeft, width - marginRight]);
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("background-color", "black")
.attr("style", "max-width: 100%; height: auto;");
svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "black");
const xAxis = svg
.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0));
// Change the color of the x-axis line to white
xAxis.select(".domain").attr("stroke", "white");
// Change the color of the ticks to white
xAxis.selectAll(".tick line").attr("stroke", "white");
// Change the color of the tick labels (text) to white
xAxis
.selectAll(".tick text")
.attr("fill", "white")
.style("font-family", "Ubuntu") // Set the font family
.style("font-size", "12px") // Set the font size
.style("font-weight", "bold");
// Processed data from dodge function
const processedData = dodge(alone, {
radius: radius * 2 + padding,
x: (d) => x(d["days_lasted"])
});
// Create group elements for each data point
const groups = svg
.selectAll("g.data-point")
.data(processedData)
.enter()
.append("g")
.attr("class", "data-point")
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut);
// Append circles inside each group
groups
.append("circle")
.attr("cx", (d) => d.x)
.attr("cy", (d) => height / 2 - radius - padding - d.y)
.attr("r", radius)
.attr("stroke", (d) => {
if (d.data.WinnerLabel === "Winner") {
return "gold"; // Gold for winners
} else {
return d.data.gender === "Male" ? "lightblue" : "lightpink"; // Lightblue for male, lightpink for female
}
})
.attr("stroke-width", 3);
// Append images inside each group
groups
.append("image")
.attr("xlink:href", (d) => d.data.image_url)
.attr("x", (d) => d.x - radius)
.attr("y", (d) => height / 2 - radius - padding - d.y - radius)
.attr("width", radius * 2)
.attr("height", radius * 2)
.attr(
"clip-path",
"circle(" + radius + "px at " + radius + "px " + radius + "px)"
)
.attr("preserveAspectRatio", "xMidYMid slice");
const tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("background", "lightsteelblue")
.style("border-radius", "5px")
.style("padding", "10px")
.style("color", "black")
.style("position", "absolute")
.style("text-align", "center")
.style("visibility", "hidden");
// Function to handle mouseover event
function handleMouseOver(event, d) {
const x = event.pageX;
const y = event.pageY;
const element = d3.select(this);
// Calculate the center of the circle
const centerX = d.x;
const centerY = height / 2 - radius - padding - d.y;
tooltip
.html(d.data.name) // Use the 'name' property from your data
.style("visibility", "visible")
.style("left", `${x}px`)
.style("top", `${y}px`)
.style(
"background-color",
d.data.gender === "Male" ? "lightblue" : "lightpink"
);
element
.selectAll("circle, image")
.raise() // Bring the element to the top in the SVG stacking context
.transition()
.duration(200)
// Scale around the center of the circle
.attr(
"transform",
`translate(${centerX},${centerY}) scale(${popScale}) translate(${-centerX},${-centerY})`
);
}
// Function to handle mouseout event
function handleMouseOut(event, d) {
const element = d3.select(this);
// Calculate the center of the circle
const centerX = d.x;
const centerY = height / 2 - radius - padding - d.y;
tooltip.style("visibility", "hidden");
element
.selectAll("circle, image")
.transition()
.duration(200)
// Scale back to normal around the center of the circle
.attr(
"transform",
`translate(${centerX},${centerY}) scale(1) translate(${-centerX},${-centerY})`
);
}
// Optionally, create a clipping path for circular images
svg
.append("defs")
.append("clipPath")
.attr("id", "circle-clip")
.append("circle")
.attr("cx", radius)
.attr("cy", radius)
.attr("r", radius);
return svg.node();
}