chart = {
const projection = d3.geoMercator();
const width = 900;
const height = (() => {
const [[x0, y0], [x1, y1]] = d3
.geoPath(projection.fitWidth(width, countries))
.bounds(countries);
const dy = Math.ceil(y1 - y0);
const l = Math.min(Math.ceil(x1 - x0), dy);
projection.scale((projection.scale() * (l - 1)) / l).precision(0.2);
return dy;
})();
const project = (data) => {
const { features } = data;
return features.flatMap((feature) => {
const { coordinates: C, type } = feature.geometry;
const coordinates = type === "MultiPolygon" ? C.flatMap((d) => d) : C;
const points = coordinates.map((coordinate) => {
const P = coordinate.map(projection);
return {
name: feature.properties.name,
x: P.map((d) => d[0]),
y: P.map((d) => d[1])
};
});
return points;
});
};
const cityNameValue = new Map();
const valueByCityName = (name) => {
if (cityNameValue.has(name)) return cityNameValue.get(name);
const value = [Math.random(), Math.random()];
cityNameValue.set(name, value);
return value;
};
const chart = new G2.Chart({
width,
height
});
chart
.polygon()
.data({
value: countries,
transform: [{ type: "custom", callback: project }]
})
.scale("x", { guide: null })
.scale("y", { guide: null, range: [0, 1] })
.scale("color", { type: "identity" })
.scale("tooltip", { field: "A" })
.scale("tooltip1", { field: "B" })
.encode("x", "x")
.encode("y", "y")
.encode("key", (d, i) => `${d.name}-${i}`)
.encode("color", (d) => d3.interpolateCool(valueByCityName(d.name)[0]))
.encode("title", "name")
.encode("tooltip", (d) => d3.format(".2f")(valueByCityName(d.name)[0]))
.encode("tooltip1", (d) => d3.format(".2f")(valueByCityName(d.name)[1]))
.animate("enter", { type: null })
.style("stroke", "black");
chart.interaction({ type: "elementActive", color: "black" });
return node(chart.render());
}