becomap 1.7.30 → 1.7.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,340 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MapLibre + Three.js Demo - Extruded Polygons + 3D Markers</title>
7
+
8
+ <!-- MapLibre GL CSS -->
9
+ <link href="https://unpkg.com/maplibre-gl@4.0.0/dist/maplibre-gl.css" rel="stylesheet" />
10
+
11
+ <style>
12
+ body {
13
+ margin: 0;
14
+ padding: 0;
15
+ font-family: Arial, sans-serif;
16
+ }
17
+ #map {
18
+ position: absolute;
19
+ top: 0;
20
+ bottom: 0;
21
+ width: 100%;
22
+ }
23
+ .marker-label {
24
+ font-size: 14px;
25
+ font-weight: bold;
26
+ color: #333;
27
+ pointer-events: none;
28
+ white-space: nowrap;
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 8px;
32
+ text-shadow:
33
+ -1px -1px 0 #fff,
34
+ 1px -1px 0 #fff,
35
+ -1px 1px 0 #fff,
36
+ 1px 1px 0 #fff,
37
+ 0 0 4px rgba(255,255,255,0.8);
38
+ }
39
+ .marker-icon {
40
+ width: 24px;
41
+ height: 24px;
42
+ border-radius: 50%;
43
+ border: 3px solid #fff;
44
+ box-shadow: 0 2px 4px rgba(0,0,0,0.3);
45
+ flex-shrink: 0;
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ font-size: 12px;
50
+ font-weight: bold;
51
+ color: #fff;
52
+ }
53
+ .info {
54
+ position: absolute;
55
+ top: 10px;
56
+ left: 10px;
57
+ background: rgba(255, 255, 255, 0.9);
58
+ padding: 10px;
59
+ border-radius: 4px;
60
+ z-index: 1;
61
+ }
62
+ </style>
63
+ </head>
64
+ <body>
65
+ <div id="map"></div>
66
+ <div class="info">
67
+ <strong>Demo:</strong> MapLibre extruded polygons + Three.js markers with text
68
+ </div>
69
+
70
+ <!-- MapLibre GL JS -->
71
+ <script src="https://unpkg.com/maplibre-gl@4.0.0/dist/maplibre-gl.js"></script>
72
+
73
+ <!-- Import map for Three.js modules -->
74
+ <script type="importmap">
75
+ {
76
+ "imports": {
77
+ "three": "https://unpkg.com/three@0.172.0/build/three.module.js",
78
+ "three/addons/": "https://unpkg.com/three@0.172.0/examples/jsm/"
79
+ }
80
+ }
81
+ </script>
82
+
83
+ <script type="module">
84
+ import * as THREE from 'three';
85
+ import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
86
+
87
+ // Initialize MapLibre map
88
+ const map = new maplibregl.Map({
89
+ container: 'map',
90
+ style: 'https://demotiles.maplibre.org/style.json',
91
+ center: [-122.4194, 37.7749], // San Francisco
92
+ zoom: 16,
93
+ pitch: 60,
94
+ bearing: -17.6,
95
+ antialias: true
96
+ });
97
+
98
+ map.on('load', () => {
99
+ // Add 4 extruded polygons (buildings)
100
+ const buildings = {
101
+ 'type': 'FeatureCollection',
102
+ 'features': [
103
+ {
104
+ 'type': 'Feature',
105
+ 'properties': { 'height': 50, 'color': '#4A90E2' },
106
+ 'geometry': {
107
+ 'type': 'Polygon',
108
+ 'coordinates': [[
109
+ [-122.4204, 37.7759],
110
+ [-122.4194, 37.7759],
111
+ [-122.4194, 37.7749],
112
+ [-122.4204, 37.7749],
113
+ [-122.4204, 37.7759]
114
+ ]]
115
+ }
116
+ },
117
+ {
118
+ 'type': 'Feature',
119
+ 'properties': { 'height': 70, 'color': '#E94B3C' },
120
+ 'geometry': {
121
+ 'type': 'Polygon',
122
+ 'coordinates': [[
123
+ [-122.4184, 37.7759],
124
+ [-122.4174, 37.7759],
125
+ [-122.4174, 37.7749],
126
+ [-122.4184, 37.7749],
127
+ [-122.4184, 37.7759]
128
+ ]]
129
+ }
130
+ },
131
+ {
132
+ 'type': 'Feature',
133
+ 'properties': { 'height': 40, 'color': '#50C878' },
134
+ 'geometry': {
135
+ 'type': 'Polygon',
136
+ 'coordinates': [[
137
+ [-122.4204, 37.7739],
138
+ [-122.4194, 37.7739],
139
+ [-122.4194, 37.7729],
140
+ [-122.4204, 37.7729],
141
+ [-122.4204, 37.7739]
142
+ ]]
143
+ }
144
+ },
145
+ {
146
+ 'type': 'Feature',
147
+ 'properties': { 'height': 60, 'color': '#F39C12' },
148
+ 'geometry': {
149
+ 'type': 'Polygon',
150
+ 'coordinates': [[
151
+ [-122.4184, 37.7739],
152
+ [-122.4174, 37.7739],
153
+ [-122.4174, 37.7729],
154
+ [-122.4184, 37.7729],
155
+ [-122.4184, 37.7739]
156
+ ]]
157
+ }
158
+ }
159
+ ]
160
+ };
161
+
162
+ // Add source for buildings
163
+ map.addSource('buildings', {
164
+ 'type': 'geojson',
165
+ 'data': buildings
166
+ });
167
+
168
+ // Add extruded polygon layer
169
+ map.addLayer({
170
+ 'id': 'buildings-3d',
171
+ 'type': 'fill-extrusion',
172
+ 'source': 'buildings',
173
+ 'paint': {
174
+ 'fill-extrusion-color': ['get', 'color'],
175
+ 'fill-extrusion-height': ['get', 'height'],
176
+ 'fill-extrusion-base': 0,
177
+ 'fill-extrusion-opacity': 0.8
178
+ }
179
+ });
180
+
181
+ // Add Three.js custom layer for markers
182
+ addThreeJSMarkers();
183
+ });
184
+
185
+ function addThreeJSMarkers() {
186
+ // Marker positions (lng, lat, height)
187
+ const markers = [
188
+ { position: [-122.4199, 37.7754, 55], label: 'Building A', color: 0x4A90E2 },
189
+ { position: [-122.4179, 37.7754, 75], label: 'Building B', color: 0xE94B3C },
190
+ { position: [-122.4199, 37.7734, 45], label: 'Building C', color: 0x50C878 },
191
+ { position: [-122.4179, 37.7734, 65], label: 'Building D', color: 0xF39C12 }
192
+ ];
193
+
194
+ const customLayer = {
195
+ id: 'threejs-markers',
196
+ type: 'custom',
197
+ renderingMode: '3d',
198
+
199
+ onAdd: function(map, gl) {
200
+ // Three.js setup
201
+ this.camera = new THREE.Camera();
202
+ this.scene = new THREE.Scene();
203
+
204
+ // WebGL renderer
205
+ this.renderer = new THREE.WebGLRenderer({
206
+ canvas: map.getCanvas(),
207
+ context: gl,
208
+ antialias: true
209
+ });
210
+ this.renderer.autoClear = false;
211
+
212
+ // CSS2D renderer for text labels
213
+ this.labelRenderer = new CSS2DRenderer();
214
+ this.labelRenderer.setSize(map.getCanvas().clientWidth, map.getCanvas().clientHeight);
215
+ this.labelRenderer.domElement.style.position = 'absolute';
216
+ this.labelRenderer.domElement.style.top = '0';
217
+ this.labelRenderer.domElement.style.pointerEvents = 'none';
218
+ map.getContainer().appendChild(this.labelRenderer.domElement);
219
+
220
+ // Add lighting
221
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
222
+ this.scene.add(ambientLight);
223
+
224
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
225
+ directionalLight.position.set(10, 50, 10);
226
+ this.scene.add(directionalLight);
227
+
228
+ // Create markers
229
+ markers.forEach(markerData => {
230
+ const [lng, lat, height] = markerData.position;
231
+ const mercator = maplibregl.MercatorCoordinate.fromLngLat([lng, lat], height);
232
+ const modelScale = mercator.meterInMercatorCoordinateUnits();
233
+
234
+ // Create icon sprite (circular marker)
235
+ const canvas = document.createElement('canvas');
236
+ canvas.width = 256;
237
+ canvas.height = 256;
238
+ const ctx = canvas.getContext('2d');
239
+
240
+ // Draw circular icon with shadow
241
+ ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
242
+ ctx.shadowBlur = 10;
243
+ ctx.shadowOffsetX = 0;
244
+ ctx.shadowOffsetY = 5;
245
+
246
+ ctx.fillStyle = '#' + markerData.color.toString(16).padStart(6, '0');
247
+ ctx.beginPath();
248
+ ctx.arc(128, 128, 80, 0, Math.PI * 2);
249
+ ctx.fill();
250
+
251
+ // Draw white border
252
+ ctx.shadowColor = 'transparent';
253
+ ctx.strokeStyle = '#ffffff';
254
+ ctx.lineWidth = 12;
255
+ ctx.stroke();
256
+
257
+ // Draw letter "P" or first letter of label
258
+ ctx.fillStyle = '#ffffff';
259
+ ctx.font = 'bold 100px Arial';
260
+ ctx.textAlign = 'center';
261
+ ctx.textBaseline = 'middle';
262
+ ctx.fillText(markerData.label.charAt(0), 128, 128);
263
+
264
+ // Create sprite from canvas
265
+ const texture = new THREE.CanvasTexture(canvas);
266
+ const spriteMaterial = new THREE.SpriteMaterial({
267
+ map: texture,
268
+ sizeAttenuation: true,
269
+ depthTest: true,
270
+ depthWrite: false
271
+ });
272
+ const sprite = new THREE.Sprite(spriteMaterial);
273
+
274
+ // Scale sprite to be visible (in meters)
275
+ const spriteSize = 15; // 15 meters
276
+ sprite.scale.set(spriteSize * modelScale, spriteSize * modelScale, 1);
277
+
278
+ // Position sprite
279
+ sprite.position.set(
280
+ mercator.x,
281
+ mercator.y,
282
+ mercator.z
283
+ );
284
+
285
+ this.scene.add(sprite);
286
+
287
+ // Create text label with icon using CSS2D
288
+ const labelDiv = document.createElement('div');
289
+ labelDiv.className = 'marker-label';
290
+
291
+ // Create icon element
292
+ const iconDiv = document.createElement('div');
293
+ iconDiv.className = 'marker-icon';
294
+ iconDiv.style.backgroundColor = '#' + markerData.color.toString(16).padStart(6, '0');
295
+ iconDiv.textContent = markerData.label.charAt(0); // First letter
296
+
297
+ // Create text element
298
+ const textSpan = document.createElement('span');
299
+ textSpan.textContent = markerData.label;
300
+
301
+ // Append icon and text to label
302
+ labelDiv.appendChild(iconDiv);
303
+ labelDiv.appendChild(textSpan);
304
+
305
+ const label = new CSS2DObject(labelDiv);
306
+ // Position label to the left of the marker
307
+ const labelOffset = 20 * modelScale; // 20 meters to the left
308
+ label.position.set(
309
+ mercator.x - labelOffset,
310
+ mercator.y,
311
+ mercator.z
312
+ );
313
+
314
+ this.scene.add(label);
315
+ });
316
+
317
+ this.map = map;
318
+ },
319
+
320
+ render: function(gl, matrix) {
321
+ // Update camera matrix
322
+ this.camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
323
+
324
+ // Render Three.js scene
325
+ this.renderer.resetState();
326
+ this.renderer.render(this.scene, this.camera);
327
+
328
+ // Render CSS2D labels
329
+ this.labelRenderer.render(this.scene, this.camera);
330
+
331
+ // Trigger map repaint
332
+ this.map.triggerRepaint();
333
+ }
334
+ };
335
+
336
+ map.addLayer(customLayer);
337
+ }
338
+ </script>
339
+ </body>
340
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "becomap",
3
- "version": "1.7.30",
3
+ "version": "1.7.32",
4
4
  "description": "we lib to display becomap",
5
5
  "main": "lib/becomap.js",
6
6
  "module": "lib/becomap.js",