mirror of
https://github.com/AnmolSaini16/mapcn
synced 2026-04-26 00:14:56 +02:00
24 lines
5.7 KiB
JSON
24 lines
5.7 KiB
JSON
{
|
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
"name": "heatmap",
|
|
"title": "Heatmap",
|
|
"description": "Globe-projected heatmap visualizing earthquake density with zoom-dependent styling.",
|
|
"dependencies": [],
|
|
"registryDependencies": [
|
|
"map",
|
|
"card"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "src/registry/blocks/heatmap/page.tsx",
|
|
"content": "\"use client\";\n\nimport { useEffect, useId } from \"react\";\n\nimport { Map, useMap } from \"@/registry/map\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\n\nconst EARTHQUAKE_GEOJSON_URL =\n \"https://maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson\";\n\nconst HEATMAP_GRADIENT_COLORS = [\n \"#fff7bc\",\n \"#fee391\",\n \"#fec44f\",\n \"#fe9929\",\n \"#d7301f\",\n];\n\nconst HEATMAP_COLOR_STOPS: [number, string][] = [\n [0.15, HEATMAP_GRADIENT_COLORS[0]],\n [0.35, HEATMAP_GRADIENT_COLORS[1]],\n [0.55, HEATMAP_GRADIENT_COLORS[2]],\n [0.75, HEATMAP_GRADIENT_COLORS[3]],\n [1, HEATMAP_GRADIENT_COLORS[4]],\n];\n\nfunction GlobeHeatmapLayers() {\n const { map, isLoaded } = useMap();\n const id = useId();\n const sourceId = `heatmap-source-${id}`;\n const heatLayerId = `heatmap-layer-${id}`;\n const pointLayerId = `heatmap-point-layer-${id}`;\n\n useEffect(() => {\n if (!map || !isLoaded) return;\n\n if (!map.getSource(sourceId)) {\n map.addSource(sourceId, {\n type: \"geojson\",\n data: EARTHQUAKE_GEOJSON_URL,\n });\n }\n\n if (!map.getLayer(heatLayerId)) {\n map.addLayer({\n id: heatLayerId,\n type: \"heatmap\",\n source: sourceId,\n maxzoom: 6,\n paint: {\n \"heatmap-weight\": [\n \"interpolate\",\n [\"linear\"],\n [\"get\", \"mag\"],\n 0,\n 0,\n 6,\n 0.8,\n ],\n \"heatmap-intensity\": [\n \"interpolate\",\n [\"linear\"],\n [\"zoom\"],\n 0,\n 0.55,\n 6,\n 1.25,\n ],\n \"heatmap-color\": [\n \"interpolate\",\n [\"linear\"],\n [\"heatmap-density\"],\n 0,\n \"rgba(59, 130, 246, 0)\",\n ...HEATMAP_COLOR_STOPS.flat(),\n ],\n \"heatmap-radius\": [\"interpolate\", [\"linear\"], [\"zoom\"], 0, 8, 6, 34],\n \"heatmap-opacity\": [\n \"interpolate\",\n [\"linear\"],\n [\"zoom\"],\n 4.5,\n 0.75,\n 6.5,\n 0.08,\n ],\n },\n });\n }\n\n if (!map.getLayer(pointLayerId)) {\n map.addLayer({\n id: pointLayerId,\n type: \"circle\",\n source: sourceId,\n minzoom: 4.5,\n paint: {\n \"circle-radius\": [\n \"interpolate\",\n [\"linear\"],\n [\"get\", \"mag\"],\n 1,\n 3,\n 6,\n 10,\n ],\n \"circle-color\": [\n \"interpolate\",\n [\"linear\"],\n [\"get\", \"mag\"],\n 1,\n HEATMAP_GRADIENT_COLORS[1],\n 2.5,\n HEATMAP_GRADIENT_COLORS[2],\n 4,\n HEATMAP_GRADIENT_COLORS[3],\n 6,\n HEATMAP_GRADIENT_COLORS[4],\n ],\n \"circle-stroke-width\": 1,\n \"circle-stroke-color\": \"rgba(255,255,255,0.8)\",\n \"circle-opacity\": [\n \"interpolate\",\n [\"linear\"],\n [\"zoom\"],\n 4.5,\n 0,\n 6.5,\n 0.7,\n ],\n },\n });\n }\n\n return () => {\n try {\n if (map.getLayer(pointLayerId)) map.removeLayer(pointLayerId);\n if (map.getLayer(heatLayerId)) map.removeLayer(heatLayerId);\n if (map.getSource(sourceId)) map.removeSource(sourceId);\n } catch {\n // ignore\n }\n };\n }, [map, isLoaded, sourceId, heatLayerId, pointLayerId]);\n\n return null;\n}\n\nexport function HeatmapBlock() {\n return (\n <div className=\"bg-muted/50 relative h-screen\">\n <div className=\"relative h-full\">\n <Map\n center={[-113, 43]}\n zoom={3.2}\n projection={{ type: \"globe\" }}\n pitch={24}\n minZoom={1.2}\n maxZoom={8}\n >\n <GlobeHeatmapLayers />\n </Map>\n </div>\n\n <Card className=\"absolute top-4 left-4 z-10 w-72\">\n <CardHeader>\n <CardTitle>Global Earthquakes Heatmap</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-5 gap-1.5\">\n {HEATMAP_GRADIENT_COLORS.map((color) => (\n <span\n key={color}\n className=\"h-2.5 rounded-full\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n <div className=\"text-muted-foreground flex items-center justify-between pt-3 text-xs\">\n <span>Low</span>\n <span>High</span>\n </div>\n <p className=\"text-muted-foreground pt-2 text-xs\">\n Data source:{\" \"}\n <a\n href={EARTHQUAKE_GEOJSON_URL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hover:text-foreground underline underline-offset-4 transition-colors\"\n >\n MapLibre earthquakes.geojson\n </a>\n </p>\n </CardContent>\n </Card>\n </div>\n );\n}\n",
|
|
"type": "registry:page",
|
|
"target": "app/heatmap/page.tsx"
|
|
}
|
|
],
|
|
"categories": [
|
|
"visualization",
|
|
"heatmap"
|
|
],
|
|
"type": "registry:block"
|
|
} |