Public
Edited
Dec 10, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart2 = {
const svg = d3.create("svg").attr("viewBox", `0 0 ${width} ${height}`);

const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden");

// Function to handle click events
function handleClick(event, d) {
closeModal();
}

// function to close modal
function closeModal() {
const myModal = document.getElementById("myModal");
myModal.style.display = "none";
}

const sizeScale = d3.scaleSqrt().domain([0, d3.max(dataJoined, d => d.pop_size)]).range([5, 50]);

const colorScale = d3.scaleSequential(d3.interpolateBlues).domain([1, d3.max(dataJoined, d => d.mean_homo)]);

svg.selectAll("path")
.data(countries.features)
.enter()
.append("g")
.attr("class", "country-group")
.each(function (d) {
const countryGroup = d3.select(this);

// Append path element
countryGroup.append("path")
.attr("d", path)
.attr("stroke", "#111")
.attr("stroke-width", 0.5)
.attr("fill", "none")
// Tooltip functionality
.on("mouseover", function (event, d) {
let text = d.properties.name
const mean_homo = d.properties.dataJoined.get(year)[0].mean_homo
const mean_homo_rounded = Math.round((mean_homo + Number.EPSILON) * 100) / 100
text = text + "\nJustifiability: " + mean_homo_rounded
const year_to_show = d.properties.dataJoined.get(year)[0].displayed_year
text = text + "\nThis value is from: " + year_to_show
showToolTip(text, [event.pageX, event.pageY])
})
.on("mousemove", function (event) {
d3.select(".tooltip")
.style("top", event.pageY - 10 + "px")
.style("left", event.pageX + 10 + "px")
})
.on("mouseout", function () {
d3.select(".tooltip").style("visibility", "hidden")
})
.on("click", handleClick)
});

svg.selectAll("g")
.data(countries.features)
.each(function (d) {
const countryGroup = d3.select(this);
// Append star symbol if when_legal equals the displayed year and not already added
const whenLegalYear = d.properties.dataJoined?.get(year) ? d.properties.dataJoined.get(year)[0].when_legal : null;
const symbolAdded = whenLegalYear !== null && whenLegalYear <= year;

console.log("Symbol Added:", symbolAdded); // Log the presence of the symbolAdded condition
const [x, y] = path.centroid(d);
const countryArea = path.area(d);
// Append circle for population size and color based on rating
countryGroup.append("circle")
.attr("class", "bubble")
.attr("cx", x)
.attr("cy", y)
.attr("r", sizeScale(d.properties.dataJoined?.get(year)[0].pop_size))
// .attr("fill", colorScale(d.properties.dataJoined.get(year)[0].mean_homo))
.attr("fill", d => d.properties.dataJoined?.get(year) && !isNaN(d.properties.dataJoined?.get(year)[0].mean_homo)
? cScale(d.properties.dataJoined.get(year)[0].mean_homo)
: "lightgrey")
.style("opacity", 0.5);

if (symbolAdded) {
const [x, y] = path.centroid(d);
const countryArea = path.area(d);
const symbolSize = Math.log(countryArea) * 2; // Adjust the scaling factor as needed

console.log("Symbol Size:", symbolSize); // Log the symbol size


countryGroup.append("text")
.attr("class", "symbol")
.attr("x", x)
.attr("y", y)
.text("\u2726") // Unicode for six-pointed star symbol
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.style("font-size", `${symbolSize}px`)
.style("fill", "orange");
}
});
svg.selectAll("g")
.on("mouseover", function (event, d) {
let text = d.properties.name
const mean_homo = d.properties.dataJoined.get(year)[0].mean_homo
const mean_homo_rounded = Math.round((mean_homo + Number.EPSILON) * 100) / 100
text = text + "\nJustifiability: " + mean_homo_rounded
const year_to_show = d.properties.dataJoined.get(year)[0].displayed_year
text = text + "\nThis value is from: " + year_to_show
showToolTip(text, [event.pageX, event.pageY])
})
.on("mousemove", function (event) {
d3.select(".tooltip")
.style("top", event.pageY - 10 + "px")
.style("left", event.pageX + 10 + "px")
})
.on("mouseout", function () {
d3.select(".tooltip").style("visibility", "hidden")
});
return svg.node();

// function showToolTip(text, [x, y]) {
// tooltip.style("visibility", "visible").html(text);
// }
};
Insert cell
countries110m = FileAttachment("countries-110m.json").json()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Merge data from the second CSV into the original data array
dataJoined = data.map(d => {
const matchingRow = legalityData.find(row => row.country === d.country);
const matchingPop = popsize4.find(row => row.country === d.country);
console.log(matchingRow)
// Add the new property 'when_legal' based on the additional data
return {
...d,
when_legal: matchingRow ? +matchingRow.year : null,
pop_size: matchingPop ? +matchingPop[d.year] : null,
}
});

// Now, each object in the output array has a new 'when_legal' property based on the legality data
Insert cell
popSize@4.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
popSize@2.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
popsize3[0][data[0].year]
Insert cell
popSize@3.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3Legend = require("d3-svg-legend")
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more