85 lines
2 KiB
TypeScript
85 lines
2 KiB
TypeScript
import { onMount } from "solid-js";
|
|
import * as d3 from "d3";
|
|
import worldData from "../lib/world.json";
|
|
|
|
const GlobeComponent = () => {
|
|
let mapContainer: HTMLDivElement | undefined;
|
|
|
|
const visitedCountries = [
|
|
"France",
|
|
"China",
|
|
"Italy",
|
|
"Sri Lanka",
|
|
"Turkey",
|
|
"Greece",
|
|
"Malta",
|
|
"Hungary",
|
|
"Portugal",
|
|
"Marocco",
|
|
];
|
|
|
|
onMount(() => {
|
|
if (!mapContainer) return;
|
|
|
|
const width = mapContainer.clientWidth;
|
|
const height = 500;
|
|
const sensitivity = 75;
|
|
|
|
let projection = d3
|
|
.geoOrthographic()
|
|
.scale(250)
|
|
.center([0, 0])
|
|
.rotate([0, -30])
|
|
.translate([width / 2, height / 2]);
|
|
|
|
const initialScale = projection.scale();
|
|
let pathGenerator = d3.geoPath().projection(projection);
|
|
|
|
let svg = d3
|
|
.select(mapContainer)
|
|
.append("svg")
|
|
.attr("width", width)
|
|
.attr("height", height);
|
|
|
|
svg
|
|
.append("circle")
|
|
.attr("fill", "#EEE")
|
|
.attr("stroke", "#000")
|
|
.attr("stroke-width", "0.2")
|
|
.attr("cx", width / 2)
|
|
.attr("cy", height / 2)
|
|
.attr("r", initialScale);
|
|
|
|
let map = svg.append("g");
|
|
|
|
map
|
|
.append("g")
|
|
.attr("class", "countries")
|
|
.selectAll("path")
|
|
.data(worldData.features)
|
|
.enter()
|
|
.append("path")
|
|
.attr("d", (d: any) => pathGenerator(d as any))
|
|
.attr("fill", (d: { properties: { name: string } }) =>
|
|
visitedCountries.includes(d.properties.name) ? "#E63946" : "white"
|
|
)
|
|
.style("stroke", "black")
|
|
.style("stroke-width", 0.3)
|
|
.style("opacity", 0.8);
|
|
|
|
d3.timer(() => {
|
|
const rotate = projection.rotate();
|
|
const k = sensitivity / projection.scale();
|
|
projection.rotate([rotate[0] - 1 * k, rotate[1]]);
|
|
svg.selectAll("path").attr("d", (d: any) => pathGenerator(d as any));
|
|
}, 200);
|
|
});
|
|
|
|
return (
|
|
<div class="flex flex-col text-white justify-center items-center w-full h-full">
|
|
<div class="w-full" ref={mapContainer}></div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default GlobeComponent;
|