1
2
3
4
5
6
7
8import { MapView } from "mapgpu";
9import { GraphicsLayer, RasterTileLayer } from "mapgpu/layers";
10import { RenderEngine } from "mapgpu/render";
11import { SimpleRenderer } from "mapgpu/core";
12import { BufferAnalysis } from "mapgpu/analysis";
13
14import type { RunResultObject } from "@/components/examples/ExampleCanvas";
15
16const CENTER: [number, number] = [32.866, 39.925];
17
18export async function run(container: HTMLElement): Promise<RunResultObject> {
19 const view = new MapView({
20 container,
21 renderEngine: new RenderEngine(),
22 mode: "2d",
23 center: CENTER,
24 zoom: 6,
25 minZoom: 2,
26 maxZoom: 18,
27 backgroundColor: "transparent",
28 });
29
30 view.map.add(
31 new RasterTileLayer({
32 id: "carto-light",
33 urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
34 subdomains: ["a", "b", "c", "d"],
35 maxZoom: 19,
36 attribution: "© CARTO · © OpenStreetMap contributors",
37 }),
38 );
39
40 const buffers = new GraphicsLayer({ id: "buffers" });
41 buffers.renderer = new SimpleRenderer({
42 type: "simple-fill",
43 color: [255, 92, 26, 60],
44 outlineColor: [255, 92, 26, 230],
45 outlineWidth: 2,
46 });
47 view.map.add(buffers);
48
49 const origin = new GraphicsLayer({ id: "origin" });
50 origin.renderer = new SimpleRenderer({
51 type: "simple-marker",
52 color: [255, 92, 26, 240],
53 size: 12,
54 outlineColor: [255, 255, 255, 255],
55 outlineWidth: 2,
56 });
57 origin.add({
58 id: "center",
59 geometry: { type: "Point" as const, coordinates: CENTER },
60 attributes: {},
61 });
62 view.map.add(origin);
63
64 const analysis = new BufferAnalysis();
65
66 const applyBuffer = async (distanceKm: number) => {
67 const result = await analysis.buffer({
68 geometry: { type: "Point", coordinates: CENTER },
69 distance: distanceKm * 1000,
70 segments: 96,
71 });
72 buffers.replaceAll([
73 {
74 id: `buf-${distanceKm}`,
75 geometry: result.geometry,
76 attributes: { radiusKm: distanceKm },
77 },
78 ]);
79 };
80
81 await view.when();
82 await applyBuffer(50);
83
84 return {
85 dispose: () => view.destroy(),
86 controls: [
87 {
88 kind: "segmented",
89 id: "radius",
90 initial: "50",
91 options: [
92 { value: "10", label: "10 km" },
93 { value: "50", label: "50 km" },
94 { value: "200", label: "200 km" },
95 ],
96 onChange: async (value) => {
97 await applyBuffer(Number(value));
98 },
99 },
100 ],
101 };
102}