From 5cc77d97e5959d4f5124a4b0ec0e7ab95f813972 Mon Sep 17 00:00:00 2001 From: yuiseki Date: Sun, 11 Aug 2024 13:02:42 +0900 Subject: [PATCH] Add visualization example: heatmap --- .../Heatmap/ArmedConflict/index.stories.tsx | 14 +++++ .../Heatmap/ArmedConflict/index.tsx | 59 +++++++++++++++++++ .../Heatmap/ArmedConflict/source.ts | 49 +++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/examples/Visualization/Heatmap/ArmedConflict/index.stories.tsx create mode 100644 src/examples/Visualization/Heatmap/ArmedConflict/index.tsx create mode 100644 src/examples/Visualization/Heatmap/ArmedConflict/source.ts diff --git a/src/examples/Visualization/Heatmap/ArmedConflict/index.stories.tsx b/src/examples/Visualization/Heatmap/ArmedConflict/index.stories.tsx new file mode 100644 index 0000000..4a2d3fc --- /dev/null +++ b/src/examples/Visualization/Heatmap/ArmedConflict/index.stories.tsx @@ -0,0 +1,14 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { ArmedConflictHeatMap as MapComponent } from "."; + +const meta: Meta = { + component: MapComponent, + parameters: { + layout: "fullscreen", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Preview: Story = {}; diff --git a/src/examples/Visualization/Heatmap/ArmedConflict/index.tsx b/src/examples/Visualization/Heatmap/ArmedConflict/index.tsx new file mode 100644 index 0000000..bc626fc --- /dev/null +++ b/src/examples/Visualization/Heatmap/ArmedConflict/index.tsx @@ -0,0 +1,59 @@ +import { Protocol } from "pmtiles"; +import maplibregl from "maplibre-gl"; +import "maplibre-gl/dist/maplibre-gl.css"; +import { Layer, Map, Source } from "react-map-gl/maplibre"; +import { useEffect } from "react"; +import { ArmedConflictPMTilesHeatmapSource as source } from "./source"; + +export const ArmedConflictHeatMap = () => { + useEffect(() => { + const protocol = new Protocol(); + maplibregl.addProtocol("pmtiles", protocol.tile); + return () => { + maplibregl.removeProtocol("pmtiles"); + }; + }, []); + + return ( + + + {source.layers?.map((layer) => { + switch (layer.type) { + case "heatmap": + return ( + + ); + default: + return null; + } + })} + + + ); +}; diff --git a/src/examples/Visualization/Heatmap/ArmedConflict/source.ts b/src/examples/Visualization/Heatmap/ArmedConflict/source.ts new file mode 100644 index 0000000..8c5d52c --- /dev/null +++ b/src/examples/Visualization/Heatmap/ArmedConflict/source.ts @@ -0,0 +1,49 @@ +import { PMTilesSource } from "../../../../types/PMTilesSource"; + +export const ArmedConflictPMTilesHeatmapSource: PMTilesSource = { + id: "uppsala-armed-conflict-heatmap", + url: "pmtiles://https://data.source.coop/smartmaps/uppsala-conflict/a.pmtiles", + type: "vector", + attribution: + 'Uppsala Conflict Data Program', + maxzoom: 18, + minzoom: 2, + layers: [ + { + id: "event-heatmap-layer", + sourceLayer: "event", + type: "heatmap", + paint: { + // Increase the heatmap weight based on frequency and property magnitude + 'heatmap-weight': 0.5, + // Increase the heatmap color weight weight by zoom level + // heatmap-intensity is a multiplier on top of heatmap-weight + 'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, 18, 3], + // Color ramp for heatmap. Domain is 0 (low) to 1 (high). + // Begin color ramp at 0-stop with a 0-transparency color + // to create a blur-like effect. + 'heatmap-color': [ + 'interpolate', + ['linear'], + ['heatmap-density'], + 0, + 'rgba(33,102,172,0)', + 0.2, + 'rgb(103,169,207)', + 0.4, + 'rgb(209,229,240)', + 0.6, + 'rgb(253,219,199)', + 0.8, + 'rgb(239,138,98)', + 0.9, + 'rgb(255,201,101)' + ], + // Adjust the heatmap radius by zoom level + 'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, 18, 20], + // Transition from heatmap to circle layer by zoom level + 'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 9, 0] + }, + }, + ], +};