mapbox-gl-shadow-simulator 0.46.1 → 0.47.1
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.
- package/README.md +1 -3
- package/dist/mapbox-gl-shadow-simulator.d.ts +2 -0
- package/dist/mapbox-gl-shadow-simulator.esm.js +2 -2
- package/dist/mapbox-gl-shadow-simulator.umd.min.js +2 -2
- package/dist/shademap/leaflet-shademap/dist/ShadeMap.d.ts +121 -0
- package/dist/shademap/leaflet-shademap/dist/ShadeMapLeaflet.d.ts +14 -0
- package/dist/shademap/leaflet-shademap/dist/ShadeMapMapbox.d.ts +26 -0
- package/dist/shademap/leaflet-shademap/dist/buildings/BuildingRasterizer.d.ts +37 -0
- package/dist/shademap/leaflet-shademap/dist/buildings/fetch-buildings.d.ts +12 -0
- package/dist/shademap/leaflet-shademap/dist/buildings/normalize-buildings.d.ts +8 -0
- package/dist/shademap/leaflet-shademap/dist/components/CanvasOverlay.d.ts +11 -0
- package/dist/shademap/leaflet-shademap/dist/index.d.ts +7 -0
- package/dist/shademap/leaflet-shademap/dist/lib/EventEmitter.d.ts +10 -0
- package/dist/shademap/leaflet-shademap/dist/lib/TileMerger.d.ts +40 -0
- package/dist/shademap/leaflet-shademap/dist/lib/heightMap.d.ts +33 -0
- package/dist/shademap/leaflet-shademap/dist/lib/helpers.d.ts +27 -0
- package/dist/shademap/leaflet-shademap/dist/lib/image.d.ts +13 -0
- package/dist/shademap/leaflet-shademap/dist/lib/projection.d.ts +3 -0
- package/dist/shademap/leaflet-shademap/dist/lib/shadowMap.d.ts +16 -0
- package/dist/shademap/leaflet-shademap/dist/map/geometryLeaflet.d.ts +11 -0
- package/dist/shademap/leaflet-shademap/dist/map/umap.d.ts +26 -0
- package/dist/shademap/leaflet-shademap/dist/shader/gpu.d.ts +29 -0
- package/dist/shademap/leaflet-shademap/dist/shader/kernel.d.ts +68 -0
- package/dist/shademap/leaflet-shademap/dist/types/color.d.ts +5 -0
- package/dist/shademap/leaflet-shademap/dist/types/constants.d.ts +3 -0
- package/dist/shademap/leaflet-shademap/dist/types/quality.d.ts +5 -0
- package/dist/shademap/leaflet-shademap/dist/types/shadeMapOptions.d.ts +46 -0
- package/dist/shademap/leaflet-shademap/dist/types/shadow3DData.d.ts +20 -0
- package/examples/maplibre.html +39 -61
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Point, ValidBounds } from "../map/geometryLeaflet";
|
|
2
|
+
export declare const pad: (x: number) => string | number;
|
|
3
|
+
export interface XYZ {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
z: number;
|
|
7
|
+
}
|
|
8
|
+
export interface XYZParams {
|
|
9
|
+
upperLeft: Point;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
zoom: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const xyz: (params: XYZParams) => XYZ[];
|
|
15
|
+
export interface TileBoundsArgs {
|
|
16
|
+
upperLeft: Point;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
}
|
|
20
|
+
export declare const getTileBounds: (args: TileBoundsArgs) => ValidBounds;
|
|
21
|
+
export declare const getDeclination: (date: Date) => {
|
|
22
|
+
dec: number;
|
|
23
|
+
Hi: number;
|
|
24
|
+
};
|
|
25
|
+
export declare const randomId: () => number;
|
|
26
|
+
export declare const timeInTheSunMs: (exposureLayerColor: Uint8Array, exposureLayerOpacity: number, totalTimeIntervalInMs: number) => number;
|
|
27
|
+
export declare const UTCOffsetByTimeZone: (date?: Date, timeZone?: string | undefined) => number;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { XYZ } from "../lib/helpers";
|
|
2
|
+
export interface XYZRaster {
|
|
3
|
+
xOffset: number;
|
|
4
|
+
yOffset: number;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
z: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const createTileRaster: (xyzTiles: XYZ[]) => XYZRaster[];
|
|
10
|
+
export declare const getDimensions: (data: XYZRaster[]) => {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UMap } from "../map/umap";
|
|
2
|
+
import { CompiledKernel } from "../shader/kernel";
|
|
3
|
+
import { Color } from "../types/color";
|
|
4
|
+
import { HeightMap } from "./heightMap";
|
|
5
|
+
interface DrawShadowParams {
|
|
6
|
+
kernel: CompiledKernel;
|
|
7
|
+
map: UMap;
|
|
8
|
+
heightMap: HeightMap;
|
|
9
|
+
now: Date;
|
|
10
|
+
color: Color;
|
|
11
|
+
opacity: number;
|
|
12
|
+
maxZoom: number;
|
|
13
|
+
belowCanopy: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const drawShadow: (params: DrawShadowParams) => void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LatLng } from "../../node_modules/leaflet/src/geo/LatLng";
|
|
2
|
+
import { LatLngBounds } from "../../node_modules/leaflet/src/geo/LatLngBounds";
|
|
3
|
+
import { Bounds } from "../../node_modules/leaflet/src/geometry/Bounds";
|
|
4
|
+
import { Point } from "../../node_modules/leaflet/src/geometry/Point";
|
|
5
|
+
export { Point, Bounds, LatLngBounds, LatLng };
|
|
6
|
+
export interface ValidBounds extends Bounds {
|
|
7
|
+
getTopLeft: () => Point;
|
|
8
|
+
getBottomRight: () => Point;
|
|
9
|
+
min: Point;
|
|
10
|
+
max: Point;
|
|
11
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { LatLngLiteral, Layer, Map as LeafletMap, PointExpression } from "leaflet";
|
|
2
|
+
import { Map as MapboxGLMap } from "mapbox-gl";
|
|
3
|
+
import { LatLng, LatLngBounds, Point } from "../map/geometryLeaflet";
|
|
4
|
+
export interface UMap {
|
|
5
|
+
project: (center: LatLngLiteral, zoom: number) => Point;
|
|
6
|
+
unproject: (point: Point, zoom: number) => LatLng;
|
|
7
|
+
screenUnproject: (point: PointExpression) => LatLng;
|
|
8
|
+
getZoom: () => number;
|
|
9
|
+
getCenter: () => LatLng;
|
|
10
|
+
getBounds: () => LatLngBounds;
|
|
11
|
+
eachLayer(fn: (layer: Layer) => void): void;
|
|
12
|
+
getBearing: () => number;
|
|
13
|
+
getPitch: () => number;
|
|
14
|
+
rawMap: () => LeafletMap | MapboxGLMap;
|
|
15
|
+
isLeaflet: () => boolean;
|
|
16
|
+
getPixelDimensions: () => {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
};
|
|
20
|
+
createBounds: (args: {
|
|
21
|
+
nw: LatLngLiteral;
|
|
22
|
+
se: LatLngLiteral;
|
|
23
|
+
}) => LatLngBounds;
|
|
24
|
+
}
|
|
25
|
+
declare const uMap: (map: MapboxGLMap | LeafletMap) => UMap;
|
|
26
|
+
export default uMap;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Color } from "../types/color";
|
|
2
|
+
import { Shadow3DData } from "../types/shadow3DData";
|
|
3
|
+
import { CompiledKernel } from "./kernel";
|
|
4
|
+
export declare const updateHeightMapGPU: (compiledKernel: CompiledKernel, shadow3DData: Shadow3DData) => void;
|
|
5
|
+
export declare const updateDateGPU: (compiledKernel: CompiledKernel, params: {
|
|
6
|
+
date: Date;
|
|
7
|
+
}) => void;
|
|
8
|
+
export declare const generateShadeProfile: (compiledKernel: CompiledKernel, params: {
|
|
9
|
+
texCoords: number[][];
|
|
10
|
+
dates: Date[];
|
|
11
|
+
sunColor: number[];
|
|
12
|
+
shadeColor: number[];
|
|
13
|
+
}) => Uint8Array;
|
|
14
|
+
export declare const generateLocationShadeProfile: (compiledKernel: CompiledKernel, params: {
|
|
15
|
+
texCoord: number[];
|
|
16
|
+
dates: Date[][];
|
|
17
|
+
sunColor: number[];
|
|
18
|
+
shadeColor: number[];
|
|
19
|
+
}) => Uint8Array;
|
|
20
|
+
export declare const updateDateRangeGPU: (compiledKernel: CompiledKernel, params: {
|
|
21
|
+
startDate: Date;
|
|
22
|
+
endDate: Date;
|
|
23
|
+
iterations: number;
|
|
24
|
+
emit: (name: string, ...args: any[]) => void;
|
|
25
|
+
}) => Promise<boolean>;
|
|
26
|
+
export declare const updateColorGPU: (compiledKernel: CompiledKernel, params: {
|
|
27
|
+
color: Color;
|
|
28
|
+
opacity: number;
|
|
29
|
+
}) => void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
interface CompileProgramArgs {
|
|
2
|
+
gl: WebGLRenderingContext;
|
|
3
|
+
vSrc: string;
|
|
4
|
+
fSrc: string;
|
|
5
|
+
}
|
|
6
|
+
interface UpdateLocationArgs {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
maxHeight: number;
|
|
10
|
+
heightMapZoom: number;
|
|
11
|
+
topYCoord: number;
|
|
12
|
+
ySize: number;
|
|
13
|
+
colorVec: number[];
|
|
14
|
+
step: number;
|
|
15
|
+
west: number;
|
|
16
|
+
dLng: number;
|
|
17
|
+
dec: number;
|
|
18
|
+
Hi: number;
|
|
19
|
+
cornerClipCoords: number[];
|
|
20
|
+
cornerTextureCoords: number[];
|
|
21
|
+
outputWidth: number;
|
|
22
|
+
outputHeight: number;
|
|
23
|
+
belowCanopy: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface UpdateViewportArgs {
|
|
26
|
+
xStart: number;
|
|
27
|
+
yStart: number;
|
|
28
|
+
xEnd: number;
|
|
29
|
+
yEnd: number;
|
|
30
|
+
}
|
|
31
|
+
interface UpdateDateArgs {
|
|
32
|
+
dec: number;
|
|
33
|
+
Hi: number;
|
|
34
|
+
}
|
|
35
|
+
interface UpdateDateRangeArgs {
|
|
36
|
+
startDate: Date;
|
|
37
|
+
endDate: Date;
|
|
38
|
+
iterations: number;
|
|
39
|
+
emit: (name: string, ...args: any[]) => void;
|
|
40
|
+
}
|
|
41
|
+
interface UpdateColorArgs {
|
|
42
|
+
colorVec: number[];
|
|
43
|
+
}
|
|
44
|
+
export interface CompiledKernel {
|
|
45
|
+
updateLocation: (args: UpdateLocationArgs) => void;
|
|
46
|
+
updateViewport: (args: UpdateViewportArgs) => void;
|
|
47
|
+
updateDate: (args: UpdateDateArgs) => void;
|
|
48
|
+
updateDateRange: (args: UpdateDateRangeArgs) => Promise<boolean>;
|
|
49
|
+
updateColor: (args: UpdateColorArgs) => void;
|
|
50
|
+
generateShadeProfile: (args: {
|
|
51
|
+
texCoords: number[][];
|
|
52
|
+
dates: Date[];
|
|
53
|
+
sunColor: number[];
|
|
54
|
+
shadeColor: number[];
|
|
55
|
+
}) => Uint8Array;
|
|
56
|
+
generateLocationShadeProfile: (args: {
|
|
57
|
+
texCoord: number[];
|
|
58
|
+
dates: Date[][];
|
|
59
|
+
sunColor: number[];
|
|
60
|
+
shadeColor: number[];
|
|
61
|
+
}) => Uint8Array;
|
|
62
|
+
}
|
|
63
|
+
export declare function compileProgram(args: CompileProgramArgs): WebGLProgram;
|
|
64
|
+
interface Settings {
|
|
65
|
+
context: WebGLRenderingContext;
|
|
66
|
+
}
|
|
67
|
+
declare function kernel(settings: Settings): CompiledKernel;
|
|
68
|
+
export default kernel;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { MapboxGeoJSONFeature } from "mapbox-gl";
|
|
2
|
+
import { Quality } from "./quality";
|
|
3
|
+
import { LatLngLiteral } from "leaflet";
|
|
4
|
+
export interface TerrainSource {
|
|
5
|
+
maxZoom: number;
|
|
6
|
+
tileSize: number;
|
|
7
|
+
getSourceUrl: (params: {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
z: number;
|
|
11
|
+
}) => string;
|
|
12
|
+
getElevation: (params: {
|
|
13
|
+
r: number;
|
|
14
|
+
g: number;
|
|
15
|
+
b: number;
|
|
16
|
+
a: number;
|
|
17
|
+
}) => number;
|
|
18
|
+
_overzoom: number;
|
|
19
|
+
}
|
|
20
|
+
export interface DSMSource {
|
|
21
|
+
data: Uint8ClampedArray;
|
|
22
|
+
bounds: LatLngLiteral[];
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
maxHeight: number;
|
|
26
|
+
}
|
|
27
|
+
export interface SunExposureOptions {
|
|
28
|
+
startDate: Date;
|
|
29
|
+
endDate: Date;
|
|
30
|
+
iterations?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface SunExposure extends SunExposureOptions {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface ShadeMapOptions {
|
|
36
|
+
date?: Date;
|
|
37
|
+
color?: string;
|
|
38
|
+
opacity?: number;
|
|
39
|
+
quality?: Quality;
|
|
40
|
+
sunExposure?: SunExposure;
|
|
41
|
+
terrainSource?: TerrainSource;
|
|
42
|
+
dsmSource?: DSMSource;
|
|
43
|
+
getFeatures?: () => Promise<MapboxGeoJSONFeature[]>;
|
|
44
|
+
apiKey: string;
|
|
45
|
+
debug?: (msg: string) => void;
|
|
46
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Color } from "./color";
|
|
2
|
+
export interface Shadow3DData {
|
|
3
|
+
imageData: Uint8ClampedArray;
|
|
4
|
+
maxHeight: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
date: Date;
|
|
8
|
+
heightMapZoom: number;
|
|
9
|
+
topYCoord: number;
|
|
10
|
+
ySize: number;
|
|
11
|
+
color: Color;
|
|
12
|
+
opacity: number;
|
|
13
|
+
west: number;
|
|
14
|
+
dLng: number;
|
|
15
|
+
cornerClipCoords: number[];
|
|
16
|
+
cornerTextureCoords: number[];
|
|
17
|
+
outputWidth: number;
|
|
18
|
+
outputHeight: number;
|
|
19
|
+
belowCanopy: boolean;
|
|
20
|
+
}
|
package/examples/maplibre.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.css' />
|
|
9
9
|
<script src='https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.js'></script>
|
|
10
10
|
<script src='https://www.unpkg.com/suncalc@1.9.0/suncalc.js'></script>
|
|
11
|
-
<script src=
|
|
11
|
+
<script src='https://unpkg.com/protomaps-themes-base@2.0.0-alpha.5/dist/index.js'></script>
|
|
12
12
|
<script src="../dist/mapbox-gl-shadow-simulator.umd.min.js"></script>
|
|
13
13
|
<style>
|
|
14
14
|
body {
|
|
@@ -84,9 +84,31 @@
|
|
|
84
84
|
});
|
|
85
85
|
};
|
|
86
86
|
/* Maplibregl setup */
|
|
87
|
+
maplibregl.setRTLTextPlugin(
|
|
88
|
+
'https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js',
|
|
89
|
+
true // Lazy load the plugin
|
|
90
|
+
);
|
|
91
|
+
|
|
87
92
|
const map = new maplibregl.Map({
|
|
88
93
|
container: 'mapid',
|
|
89
|
-
style:
|
|
94
|
+
style: {
|
|
95
|
+
version: 8,
|
|
96
|
+
glyphs: 'https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf',
|
|
97
|
+
sources: {
|
|
98
|
+
"protomaps": {
|
|
99
|
+
type: "vector",
|
|
100
|
+
tiles: [
|
|
101
|
+
"https://cfw.shademap.app/20240207/{z}/{x}/{y}.pbf"
|
|
102
|
+
],
|
|
103
|
+
// url: "pmtiles://https://example.com/example.pmtiles",
|
|
104
|
+
// // ^-- Remember to prefix the URL with pmtiles://
|
|
105
|
+
attribution: '<a href="https://protomaps.com">Protomaps</a> © <a href="https://openstreetmap.org">OpenStreetMap</a>',
|
|
106
|
+
maxzoom: 15,
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
layers: protomaps_themes_base.default("protomaps", "light")
|
|
110
|
+
},
|
|
111
|
+
maplibreLogo: true,
|
|
90
112
|
center: { lng: -122.18578164139899, lat: 47.694878957368815 },
|
|
91
113
|
zoom: 8, // starting zoom
|
|
92
114
|
hash: true,
|
|
@@ -112,30 +134,20 @@
|
|
|
112
134
|
_overzoom: 18,
|
|
113
135
|
},
|
|
114
136
|
getFeatures: async () => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
feature.properties = {};
|
|
130
|
-
}
|
|
131
|
-
if (!feature.properties.height) {
|
|
132
|
-
feature.properties.height = 3;
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
return geojson.features;
|
|
136
|
-
}
|
|
137
|
-
} catch (e) {
|
|
138
|
-
console.error(e);
|
|
137
|
+
if (map.getZoom() >= 12) {
|
|
138
|
+
await mapLoaded(map);
|
|
139
|
+
const buildingData = map
|
|
140
|
+
.querySourceFeatures("protomaps", { sourceLayer: "buildings" })
|
|
141
|
+
|
|
142
|
+
buildingData.forEach(feature => { feature.properties.height = feature.properties.height || 3.1 })
|
|
143
|
+
|
|
144
|
+
// Buildings segments must be rasterized from bottom to top. If not, the base of a building
|
|
145
|
+
// could rasterize over the top tower of the building
|
|
146
|
+
buildingData.sort((a, b) => {
|
|
147
|
+
return a.properties.height - b.properties.height;
|
|
148
|
+
});
|
|
149
|
+
return buildingData;
|
|
150
|
+
|
|
139
151
|
}
|
|
140
152
|
return [];
|
|
141
153
|
},
|
|
@@ -146,40 +158,6 @@
|
|
|
146
158
|
loaderEl.innerText = `Loading: ${(loadedTiles / totalTiles * 100).toFixed(0)}%`;
|
|
147
159
|
});
|
|
148
160
|
});
|
|
149
|
-
|
|
150
|
-
async function addExtrusion() {
|
|
151
|
-
try {
|
|
152
|
-
if (map.getZoom() > 15) {
|
|
153
|
-
const bounds = map.getBounds();
|
|
154
|
-
const north = bounds.getNorth();
|
|
155
|
-
const south = bounds.getSouth();
|
|
156
|
-
const east = bounds.getEast();
|
|
157
|
-
const west = bounds.getWest();
|
|
158
|
-
const query = `https://overpass-api.de/api/interpreter?data=%2F*%0AThis%20has%20been%20generated%20by%20the%20overpass-turbo%20wizard.%0AThe%20original%20search%20was%3A%0A%E2%80%9Cbuilding%E2%80%9D%0A*%2F%0A%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0A%2F%2F%20gather%20results%0A%28%0A%20%20%2F%2F%20query%20part%20for%3A%20%E2%80%9Cbuilding%E2%80%9D%0A%20%20way%5B%22building%22%5D%28${south}%2C${west}%2C${north}%2C${east}%29%3B%0A%29%3B%0A%2F%2F%20print%20results%0Aout%20body%3B%0A%3E%3B%0Aout%20skel%20qt%3B`;
|
|
159
|
-
const response = await fetch(query)
|
|
160
|
-
const json = await response.json();
|
|
161
|
-
const geojson = osmtogeojson(json);
|
|
162
|
-
// If no building height, default to one storey of 3 meters
|
|
163
|
-
geojson.features.forEach(feature => {
|
|
164
|
-
if (!feature.properties) {
|
|
165
|
-
feature.properties = {};
|
|
166
|
-
}
|
|
167
|
-
if (!feature.properties.height) {
|
|
168
|
-
feature.properties.height = 3;
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
map.addSource('buildings3d', {
|
|
172
|
-
type: 'geojson',
|
|
173
|
-
data: geojson
|
|
174
|
-
});
|
|
175
|
-
map.addLayer('')
|
|
176
|
-
}
|
|
177
|
-
} catch (e) {
|
|
178
|
-
console.error(e);
|
|
179
|
-
}
|
|
180
|
-
return [];
|
|
181
|
-
|
|
182
|
-
}
|
|
183
161
|
/* End ShadeMap setup */
|
|
184
162
|
|
|
185
163
|
/* Controls setup */
|
|
@@ -251,4 +229,4 @@
|
|
|
251
229
|
</script>
|
|
252
230
|
</body>
|
|
253
231
|
|
|
254
|
-
</html>
|
|
232
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapbox-gl-shadow-simulator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.1",
|
|
4
4
|
"description": "Display terrain and structure shadows cast by the sun in a custom style layer",
|
|
5
5
|
"main": "dist/mapbox-gl-shadow-simulator.umd.min.js",
|
|
6
6
|
"browser": "dist/mapbox-gl-shadow-simulator.umd.min.js",
|