All exampleslayerslayer-group
§ examples · layers

Layer Group

Three layers (regions · rivers · cities) grouped under a single LayerGroup handle. Toggle cascades visibility to every child, segmented control sweeps opacity from 100% → 25%.

sluglayer-group
source136 lines
statuslive
tsexamples-src/layer-group.ts
1/**
2 * Layer Group — compose multiple layers under one LayerGroup handle.
3 * `group.visible = false` cascades the flip to every child layer; the
4 * individual layers are still the ones rendered by the engine. Useful
5 * for "tactical overlay" style toggles where you want to hide an entire
6 * data set with a single call.
7 */
8 
9import { MapView } from "mapgpu";
10import { GeoJSONLayer, LayerGroup, RasterTileLayer } from "mapgpu/layers";
11import { RenderEngine } from "mapgpu/render";
12import { SimpleRenderer } from "mapgpu/core";
13 
14import type { RunResultObject } from "@/components/examples/ExampleCanvas";
15 
16const CITIES = {
17 type: "FeatureCollection" as const,
18 features: [
19 { type: "Feature" as const, properties: {}, geometry: { type: "Point" as const, coordinates: [32.866, 39.925] } },
20 { type: "Feature" as const, properties: {}, geometry: { type: "Point" as const, coordinates: [28.979, 41.015] } },
21 { type: "Feature" as const, properties: {}, geometry: { type: "Point" as const, coordinates: [27.140, 38.423] } },
22 ],
23};
24 
25const RIVERS = {
26 type: "FeatureCollection" as const,
27 features: [
28 {
29 type: "Feature" as const,
30 properties: {},
31 geometry: {
32 type: "LineString" as const,
33 coordinates: [[38.4, 39.6], [36.8, 39.2], [35.2, 40.1], [34.0, 41.5]],
34 },
35 },
36 ],
37};
38 
39const REGIONS = {
40 type: "FeatureCollection" as const,
41 features: [
42 {
43 type: "Feature" as const,
44 properties: {},
45 geometry: {
46 type: "Polygon" as const,
47 coordinates: [[[30.5, 37.2], [36.5, 37.5], [33.8, 41.0], [30.5, 37.2]]],
48 },
49 },
50 ],
51};
52 
53export async function run(container: HTMLElement): Promise<RunResultObject> {
54 const view = new MapView({
55 container,
56 renderEngine: new RenderEngine(),
57 mode: "2d",
58 center: [35, 39.5],
59 zoom: 5,
60 minZoom: 2,
61 maxZoom: 18,
62 backgroundColor: "transparent",
63 });
64 
65 view.map.add(
66 new RasterTileLayer({
67 id: "osm",
68 urlTemplate: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
69 maxZoom: 19,
70 attribution: "© OpenStreetMap contributors",
71 }),
72 );
73 
74 const regions = new GeoJSONLayer({ id: "regions", data: REGIONS });
75 regions.renderer = new SimpleRenderer({
76 type: "simple-fill",
77 color: [255, 92, 26, 45],
78 outlineColor: [255, 92, 26, 220],
79 outlineWidth: 2,
80 });
81 const rivers = new GeoJSONLayer({ id: "rivers", data: RIVERS });
82 rivers.renderer = new SimpleRenderer({
83 type: "simple-line",
84 color: [67, 176, 255, 220],
85 width: 2.5,
86 style: "solid",
87 });
88 const cities = new GeoJSONLayer({ id: "cities", data: CITIES });
89 cities.renderer = new SimpleRenderer({
90 type: "simple-marker",
91 color: [255, 92, 26, 240],
92 size: 9,
93 outlineColor: [255, 255, 255, 255],
94 outlineWidth: 2,
95 });
96 
97 for (const l of [regions, rivers, cities]) view.map.add(l);
98 
99 // LayerGroup is a management handle — not itself rendered. Flipping
100 // visibility / opacity on the group cascades to every child.
101 const group = new LayerGroup({
102 id: "tactical-overlay",
103 layers: [regions, rivers, cities],
104 });
105 
106 await view.when();
107 
108 return {
109 dispose: () => view.destroy(),
110 controls: [
111 {
112 kind: "toggle",
113 id: "visible",
114 labels: ["hide all", "show all"],
115 initial: true,
116 onChange: (on) => {
117 group.visible = on;
118 },
119 },
120 {
121 kind: "segmented",
122 id: "opacity",
123 initial: "1",
124 options: [
125 { value: "1", label: "100%" },
126 { value: "0.6", label: "60%" },
127 { value: "0.25", label: "25%" },
128 ],
129 onChange: (value) => {
130 group.opacity = Number(value);
131 },
132 },
133 ],
134 };
135}