mapbox-gl-shadow-simulator 0.61.1 → 0.62.0
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 +18 -1
- package/dist/mapbox-gl-shadow-simulator.d.ts +3 -0
- package/dist/mapbox-gl-shadow-simulator.esm.js +2 -2
- package/dist/mapbox-gl-shadow-simulator.umd.min.js +2 -2
- package/examples/map.html +246 -196
- package/examples/maplibre.html +257 -214
- package/examples/markers-maplibre.html +304 -0
- package/examples/markers.html +197 -0
- package/package.json +1 -1
- package/dist/leaflet-shademap/leaflet-shademap/dist/ShadeMap.d.ts +0 -122
- package/dist/leaflet-shademap/leaflet-shademap/dist/ShadeMapLeaflet.d.ts +0 -17
- package/dist/leaflet-shademap/leaflet-shademap/dist/ShadeMapMapbox.d.ts +0 -29
- package/dist/leaflet-shademap/leaflet-shademap/dist/buildings/BuildingRasterizer.d.ts +0 -42
- package/dist/leaflet-shademap/leaflet-shademap/dist/buildings/fetch-buildings.d.ts +0 -12
- package/dist/leaflet-shademap/leaflet-shademap/dist/buildings/normalize-buildings.d.ts +0 -8
- package/dist/leaflet-shademap/leaflet-shademap/dist/components/CanvasOverlay.d.ts +0 -11
- package/dist/leaflet-shademap/leaflet-shademap/dist/index.d.ts +0 -7
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/EventEmitter.d.ts +0 -10
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/TileMerger.d.ts +0 -49
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/heightMap.d.ts +0 -33
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/helpers.d.ts +0 -33
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/image.d.ts +0 -13
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/projection.d.ts +0 -3
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/shadowMap.d.ts +0 -17
- package/dist/leaflet-shademap/leaflet-shademap/dist/lib/webgl.d.ts +0 -13
- package/dist/leaflet-shademap/leaflet-shademap/dist/map/geometryLeaflet.d.ts +0 -11
- package/dist/leaflet-shademap/leaflet-shademap/dist/map/umap.d.ts +0 -26
- package/dist/leaflet-shademap/leaflet-shademap/dist/shader/gpu.d.ts +0 -35
- package/dist/leaflet-shademap/leaflet-shademap/dist/shader/kernel.d.ts +0 -72
- package/dist/leaflet-shademap/leaflet-shademap/dist/types/color.d.ts +0 -5
- package/dist/leaflet-shademap/leaflet-shademap/dist/types/constants.d.ts +0 -3
- package/dist/leaflet-shademap/leaflet-shademap/dist/types/quality.d.ts +0 -5
- package/dist/leaflet-shademap/leaflet-shademap/dist/types/shadeMapOptions.d.ts +0 -46
- package/dist/leaflet-shademap/leaflet-shademap/dist/types/shadow3DData.d.ts +0 -21
package/examples/maplibre.html
CHANGED
|
@@ -2,231 +2,274 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
|
8
|
+
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.1.0/dist/maplibre-gl.css" />
|
|
9
|
+
<script src="https://unpkg.com/maplibre-gl@4.1.0/dist/maplibre-gl.js"></script>
|
|
10
|
+
<script src="https://www.unpkg.com/suncalc@1.9.0/suncalc.js"></script>
|
|
11
|
+
<script src="https://unpkg.com/protomaps-themes-base@4.3.0/dist/protomaps-themes-base.js"></script>
|
|
12
|
+
<script src="../dist/mapbox-gl-shadow-simulator.umd.min.js"></script>
|
|
13
|
+
<style>
|
|
14
|
+
body {
|
|
15
|
+
padding: 0px;
|
|
16
|
+
margin: 0px;
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
#mapid {
|
|
20
|
+
height: 100vh;
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
.maplibregl-control-time {
|
|
24
|
+
padding: 20px;
|
|
25
|
+
background-color: white;
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
#exposure-gradient-container {
|
|
29
|
+
display: none;
|
|
30
|
+
background-color: white;
|
|
31
|
+
padding: 0 10px 5px;
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
#exposure-gradient {
|
|
35
|
+
height: 20px;
|
|
36
|
+
background-image: linear-gradient(to right,
|
|
37
|
+
rgb(0 0 255/ 0.5),
|
|
38
|
+
rgb(0 255 0 / 0.5),
|
|
39
|
+
rgb(255 0 0 / 0.5));
|
|
40
|
+
display: flex;
|
|
41
|
+
}
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
#exposure-gradient>div {
|
|
44
|
+
flex: 1;
|
|
45
|
+
border: 1px solid white;
|
|
46
|
+
text-align: center;
|
|
47
|
+
font-weight: bold;
|
|
48
|
+
}
|
|
49
|
+
</style>
|
|
50
|
+
<title>mapbox-gl-shadow-simulator Maplibre Example</title>
|
|
48
51
|
</head>
|
|
49
52
|
|
|
50
53
|
<body>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
</div>
|
|
65
|
-
<div id="exposure-gradient-container">
|
|
66
|
-
<div>Hours of sunlight</div>
|
|
67
|
-
<div id="exposure-gradient"></div>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
54
|
+
<div id="mapid">
|
|
55
|
+
<div class="maplibregl-control-container" style="z-index: 2000; pointer-events: auto">
|
|
56
|
+
<div class="maplibregl-ctrl-top-left">
|
|
57
|
+
<div class="maplibregl-control-time" style="pointer-events: auto">
|
|
58
|
+
<button id="decrement">-1 hour</button>
|
|
59
|
+
<button id="increment">+1 hour</button>
|
|
60
|
+
<button id="play">Play</button>
|
|
61
|
+
<button id="stop">Stop</button>
|
|
62
|
+
<label><input id="exposure" type="checkbox" autocomplete="off" />Full-day sun exposure</label>
|
|
63
|
+
<button>
|
|
64
|
+
<a href="https://shademap.app/about" target="_blank">Get API key</a>
|
|
65
|
+
</button>
|
|
66
|
+
<span id="loader" style="padding: 3px"></span>
|
|
70
67
|
</div>
|
|
68
|
+
<div id="exposure-gradient-container">
|
|
69
|
+
<div>Hours of sunlight</div>
|
|
70
|
+
<div id="exposure-gradient"></div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
71
73
|
</div>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
</div>
|
|
75
|
+
<script>
|
|
76
|
+
const mapLoaded = (map) => {
|
|
77
|
+
return new Promise((res, rej) => {
|
|
78
|
+
function cb() {
|
|
79
|
+
if (!map.loaded()) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
map.off("render", cb);
|
|
83
|
+
res();
|
|
84
|
+
}
|
|
85
|
+
map.on("render", cb);
|
|
86
|
+
cb();
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
/* Maplibregl setup */
|
|
90
|
+
maplibregl.setRTLTextPlugin(
|
|
91
|
+
"https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js",
|
|
92
|
+
true // Lazy load the plugin
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const map = new maplibregl.Map({
|
|
96
|
+
container: "mapid",
|
|
97
|
+
style: {
|
|
98
|
+
version: 8,
|
|
99
|
+
glyphs:
|
|
100
|
+
"https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf",
|
|
101
|
+
sources: {
|
|
102
|
+
protomaps: {
|
|
103
|
+
type: "vector",
|
|
104
|
+
tiles: ["https://cfw.shademap.app/planet/{z}/{x}/{y}.pbf"],
|
|
105
|
+
attribution:
|
|
106
|
+
'<a href="https://protomaps.com">Protomaps</a> © <a href="https://openstreetmap.org">OpenStreetMap</a>',
|
|
107
|
+
maxzoom: 15,
|
|
108
|
+
},
|
|
109
|
+
buildings: {
|
|
110
|
+
type: "vector",
|
|
111
|
+
tiles: [
|
|
112
|
+
`https://cfw.shademap.app/buildings/{z}/{x}/{y}.mvt`,
|
|
113
|
+
],
|
|
114
|
+
minzoom: 14,
|
|
115
|
+
maxzoom: 14,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
layers: [
|
|
119
|
+
...protomaps_themes_base.default("protomaps", "light", "en"),
|
|
120
|
+
{
|
|
121
|
+
id: "building",
|
|
122
|
+
source: "buildings",
|
|
123
|
+
"source-layer": "building",
|
|
124
|
+
type: "line",
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
maplibreLogo: true,
|
|
129
|
+
center: { lng: -122.18578164139899, lat: 47.694878957368815 },
|
|
130
|
+
zoom: 8, // starting zoom
|
|
131
|
+
hash: true,
|
|
132
|
+
});
|
|
133
|
+
/* End Maplibregl setup */
|
|
134
|
+
|
|
135
|
+
/* ShadeMap setup */
|
|
136
|
+
const loaderEl = document.getElementById("loader");
|
|
137
|
+
let now = new Date(
|
|
138
|
+
SunCalc.getTimes(
|
|
139
|
+
new Date(),
|
|
140
|
+
47.694878957368815,
|
|
141
|
+
-122.18578164139899
|
|
142
|
+
).sunrise.getTime() +
|
|
143
|
+
60 * 60 * 1000
|
|
144
|
+
);
|
|
145
|
+
let shadeMap;
|
|
146
|
+
map.on("load", () => {
|
|
147
|
+
shadeMap = new ShadeMap({
|
|
148
|
+
apiKey:
|
|
149
|
+
"eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRwcGlvdHJvd3NraUBzaGFkZW1hcC5hcHAiLCJjcmVhdGVkIjoxNjYyNDkzMDY2Nzk0LCJpYXQiOjE2NjI0OTMwNjZ9.ovCrLTYsdKFTF6TW3DuODxCaAtGQ3qhcmqj3DWcol5g",
|
|
150
|
+
date: now,
|
|
151
|
+
color: "#01112f",
|
|
152
|
+
opacity: 0.7,
|
|
153
|
+
terrainSource: {
|
|
154
|
+
maxZoom: 15,
|
|
155
|
+
tileSize: 256,
|
|
156
|
+
getSourceUrl: ({ x, y, z }) =>
|
|
157
|
+
`https://s3.amazonaws.com/elevation-tiles-prod/terrarium/${z}/${x}/${y}.png`,
|
|
158
|
+
getElevation: ({ r, g, b, a }) => r * 256 + g + b / 256 - 32768,
|
|
159
|
+
_overzoom: 18,
|
|
160
|
+
},
|
|
161
|
+
getFeatures: async () => {
|
|
162
|
+
if (map.getZoom() >= 12) {
|
|
163
|
+
await mapLoaded(map);
|
|
164
|
+
const buildingData = map.querySourceFeatures("buildings", {
|
|
165
|
+
sourceLayer: "building",
|
|
84
166
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
92
|
-
const map = new maplibregl.Map({
|
|
93
|
-
container: 'mapid',
|
|
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/planet/{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", "en")
|
|
110
|
-
},
|
|
111
|
-
maplibreLogo: true,
|
|
112
|
-
center: { lng: -122.18578164139899, lat: 47.694878957368815 },
|
|
113
|
-
zoom: 8, // starting zoom
|
|
114
|
-
hash: true,
|
|
115
|
-
});
|
|
116
|
-
/* End Maplibregl setup */
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/* ShadeMap setup */
|
|
120
|
-
const loaderEl = document.getElementById('loader');
|
|
121
|
-
let now = new Date((SunCalc.getTimes(new Date(), 47.694878957368815, -122.18578164139899).sunrise).getTime() + 60 * 60 * 1000);
|
|
122
|
-
let shadeMap;
|
|
123
|
-
map.on('load', () => {
|
|
124
|
-
shadeMap = new ShadeMap({
|
|
125
|
-
apiKey: "eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRwcGlvdHJvd3NraUBzaGFkZW1hcC5hcHAiLCJjcmVhdGVkIjoxNjYyNDkzMDY2Nzk0LCJpYXQiOjE2NjI0OTMwNjZ9.ovCrLTYsdKFTF6TW3DuODxCaAtGQ3qhcmqj3DWcol5g",
|
|
126
|
-
date: now,
|
|
127
|
-
color: '#01112f',
|
|
128
|
-
opacity: 0.7,
|
|
129
|
-
terrainSource: {
|
|
130
|
-
maxZoom: 15,
|
|
131
|
-
tileSize: 256,
|
|
132
|
-
getSourceUrl: ({ x, y, z }) => `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/${z}/${x}/${y}.png`,
|
|
133
|
-
getElevation: ({ r, g, b, a }) => (r * 256 + g + b / 256) - 32768,
|
|
134
|
-
_overzoom: 18,
|
|
135
|
-
},
|
|
136
|
-
getFeatures: async () => {
|
|
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
|
-
|
|
151
|
-
}
|
|
152
|
-
return [];
|
|
153
|
-
},
|
|
154
|
-
debug: (msg) => { console.log(new Date().toISOString(), msg) }
|
|
155
|
-
}).addTo(map);
|
|
156
|
-
|
|
157
|
-
shadeMap.on('tileloaded', (loadedTiles, totalTiles) => {
|
|
158
|
-
loaderEl.innerText = `Loading: ${(loadedTiles / totalTiles * 100).toFixed(0)}%`;
|
|
167
|
+
|
|
168
|
+
buildingData.forEach((feature) => {
|
|
169
|
+
feature.properties.height = feature.properties.height || 3.1;
|
|
159
170
|
});
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
171
|
+
|
|
172
|
+
// Buildings segments must be rasterized from bottom to top. If not, the base of a building
|
|
173
|
+
// could rasterize over the top tower of the building
|
|
174
|
+
buildingData.sort((a, b) => {
|
|
175
|
+
return a.properties.height - b.properties.height;
|
|
176
|
+
});
|
|
177
|
+
return buildingData;
|
|
178
|
+
}
|
|
179
|
+
return [];
|
|
180
|
+
},
|
|
181
|
+
debug: (msg) => {
|
|
182
|
+
console.log(new Date().toISOString(), msg);
|
|
183
|
+
},
|
|
184
|
+
}).addTo(map);
|
|
185
|
+
|
|
186
|
+
shadeMap.on("tileloaded", (loadedTiles, totalTiles) => {
|
|
187
|
+
loaderEl.innerText = `Loading: ${(
|
|
188
|
+
(loadedTiles / totalTiles) *
|
|
189
|
+
100
|
|
190
|
+
).toFixed(0)}%`;
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
/* End ShadeMap setup */
|
|
194
|
+
|
|
195
|
+
/* Controls setup */
|
|
196
|
+
let intervalTimer;
|
|
197
|
+
|
|
198
|
+
const increment = document.getElementById("increment");
|
|
199
|
+
const decrement = document.getElementById("decrement");
|
|
200
|
+
const play = document.getElementById("play");
|
|
201
|
+
const stop = document.getElementById("stop");
|
|
202
|
+
const exposure = document.getElementById("exposure");
|
|
203
|
+
const exposureGradientContainer = document.getElementById(
|
|
204
|
+
"exposure-gradient-container"
|
|
205
|
+
);
|
|
206
|
+
const exposureGradient = document.getElementById("exposure-gradient");
|
|
207
|
+
|
|
208
|
+
increment.addEventListener(
|
|
209
|
+
"click",
|
|
210
|
+
() => {
|
|
211
|
+
now = new Date(now.getTime() + 3600000);
|
|
212
|
+
shadeMap && shadeMap.setDate(now);
|
|
213
|
+
},
|
|
214
|
+
false
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
decrement.addEventListener(
|
|
218
|
+
"click",
|
|
219
|
+
() => {
|
|
220
|
+
now = new Date(now.getTime() - 3600000);
|
|
221
|
+
shadeMap && shadeMap.setDate(now);
|
|
222
|
+
},
|
|
223
|
+
false
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
play.addEventListener("click", () => {
|
|
227
|
+
intervalTimer = setInterval(() => {
|
|
228
|
+
now = new Date(now.getTime() + 60000);
|
|
229
|
+
shadeMap && shadeMap.setDate(now);
|
|
230
|
+
}, 100);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
stop.addEventListener("click", () => {
|
|
234
|
+
clearInterval(intervalTimer);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
exposure.addEventListener("click", (e) => {
|
|
238
|
+
clearInterval(intervalTimer);
|
|
239
|
+
const target = e.target;
|
|
240
|
+
if (!target.checked) {
|
|
241
|
+
shadeMap && shadeMap.setSunExposure(false);
|
|
242
|
+
increment.disabled = false;
|
|
243
|
+
decrement.disabled = false;
|
|
244
|
+
play.disabled = false;
|
|
245
|
+
stop.disabled = false;
|
|
246
|
+
exposureGradientContainer.style.display = "none";
|
|
247
|
+
} else {
|
|
248
|
+
const { lat, lng } = map.getCenter();
|
|
249
|
+
const { sunrise, sunset } = SunCalc.getTimes(now, lat, lng);
|
|
250
|
+
shadeMap &&
|
|
251
|
+
shadeMap.setSunExposure(true, {
|
|
252
|
+
startDate: sunrise,
|
|
253
|
+
endDate: sunset,
|
|
254
|
+
});
|
|
255
|
+
increment.disabled = true;
|
|
256
|
+
decrement.disabled = true;
|
|
257
|
+
play.disabled = true;
|
|
258
|
+
stop.disabled = true;
|
|
259
|
+
|
|
260
|
+
const hours = (sunset - sunrise) / 1000 / 3600;
|
|
261
|
+
const partial = hours - Math.floor(hours);
|
|
262
|
+
const html = [];
|
|
263
|
+
for (let i = 0; i < hours; i++) {
|
|
264
|
+
html.push(`<div>${i + 1}</div>`);
|
|
265
|
+
}
|
|
266
|
+
html.push(`<div style="flex: ${partial}"></div>`);
|
|
267
|
+
exposureGradientContainer.style.display = "block";
|
|
268
|
+
exposureGradient.innerHTML = html.join("");
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
/* End controls setup */
|
|
272
|
+
</script>
|
|
230
273
|
</body>
|
|
231
274
|
|
|
232
|
-
</html>
|
|
275
|
+
</html>
|