dataviz = {
const svg = d3
.create("svg")
.style("display", "block")
.attr("viewBox", [0, 0, width, height]);
const g = svg.append("g");
const path = d3.geoPath(projection);
const radius = d3.scaleSqrt(
[0, d3.max(points.features.map((d) => d.properties.Papers))],
[0, 10]
);
g.append("g")
.selectAll("path")
.data(countries.features)
.join("path")
.attr("class", "country")
.attr("fill", "lightgrey")
.attr("d", path)
.attr("stroke", "white")
.attr("stroke-width", 0.2)
.attr("stroke-linejoin", "round");
g.append("g")
.attr("fill", "#F8BF1E")
.attr("fill-opacity", 0.5)
.selectAll("circle")
.data(points.features)
.join("circle")
.attr("cx", (d) => path_points.centroid(d)[0])
.attr("cy", (d) => path_points.centroid(d)[1])
.attr("r", (d) => radius(d.properties.Papers))
.attr("stroke-width", 0.5)
.attr("data-tippy-content", (d) => `${d.properties.School}<br /> Number of Blockchain-related Research Papers: ${d.properties.Papers}`)
g.selectAll('circle').nodes().forEach(c => tippy(c, {
allowHTML: true,
theme: "light",
}))
let zoom = d3
.zoom()
.scaleExtent([1, 16])
.translateExtent([
[0, 0],
[width, height]
])
.on("zoom", function (event, d) {
radius.range([0 / event.transform.k, 10 / event.transform.k]);
g.selectAll("path").attr("transform", event.transform);
svg
.selectAll("circle")
.attr("transform", event.transform)
.attr("r", (d) => radius(d.properties.Papers))
.attr("stroke-width", 0.5 / event.transform.k);
});
svg.call(zoom);
return svg.node();
}