Skip to content

Commit 75fa701

Browse files
committed
add stepan's projection debug page (#11226)
1 parent 07d99f4 commit 75fa701

File tree

1 file changed

+175
-142
lines changed

1 file changed

+175
-142
lines changed

debug/projections.html

Lines changed: 175 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -8,178 +8,211 @@
88
<style>
99
body { margin: 0; padding: 0; }
1010
html, body, #map { height: 100%; }
11-
.map-overlay {
12-
background-color: #fff;
13-
border-radius: 3px;
14-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
15-
font: bold 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
16-
left: 10px;
17-
padding: 10px;
18-
position: absolute;
19-
top: 10px;
20-
width: 150px;
21-
z-index: 1;
22-
}
23-
24-
fieldset {
25-
border: none;
26-
padding: 5px 0;
27-
}
28-
29-
select, input {
30-
background-color: transparent;
31-
border-radius: 3px;
32-
margin: 0;
33-
}
34-
35-
select {
36-
width: 100%;
37-
}
11+
</style>
12+
<style>
13+
.map-overlay {
14+
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
15+
position: absolute;
16+
width: 200px;
17+
top: 0;
18+
left: 0;
19+
padding: 10px;
20+
}
21+
22+
.map-overlay .map-overlay-inner {
23+
background-color: #fff;
24+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
25+
border-radius: 3px;
26+
padding: 10px;
27+
margin-bottom: 10px;
28+
}
29+
30+
.map-overlay-inner fieldset {
31+
border: none;
32+
padding: 0;
33+
margin: 0 0 10px;
34+
}
35+
36+
.map-overlay-inner fieldset:last-child {
37+
margin: 0;
38+
}
39+
40+
.map-overlay-inner select,
41+
.map-overlay-inner input {
42+
width: 100%;
43+
}
44+
45+
.map-overlay-inner label {
46+
display: block;
47+
font-weight: bold;
48+
margin: 0 0 5px;
49+
}
3850
</style>
3951
</head>
4052

4153
<body>
42-
<div class="map-overlay top">
54+
<div id='map'></div>
55+
<div class="map-overlay top">
56+
<details open>
57+
<summary>Toggle controls</summary>
58+
<div class="map-overlay-inner">
59+
<fieldset>
60+
<label>Select style</label>
61+
<select id="style" name="style">
62+
<option value="streets-v11">Streets</option>
63+
<option value="satellite-v9">Satellite</option>
64+
</select>
65+
</fieldset>
4366
<fieldset>
44-
<label>Projection:</label>
45-
<select id="projName">
46-
<option value="albers" selected>Albers USA</option>
67+
<label>Select projection</label>
68+
<select id="projection" name="projection">
69+
<option value="albers">Albers</option>
4770
<option value="equalEarth">Equal Earth</option>
4871
<option value="equirectangular">Equirectangular</option>
49-
<option value="lambertConformalConic">Lambert Conformal Conic</option>
72+
<option value="lambertConformalConic" selected>
73+
Lambert Conformal Conic
74+
</option>
5075
<option value="mercator">Mercator</option>
5176
<option value="naturalEarth">Natural Earth</option>
5277
<option value="winkelTripel">Winkel Tripel</option>
5378
</select>
5479
</fieldset>
55-
<fieldset>
56-
<label>Style:</label>
57-
<select id="styleName">
58-
<option value="streets" selected>Streets</option>
59-
<option value="satellite">Satellite</option>
60-
</select>
80+
<fieldset class="conic-param-input">
81+
<label>Center Longitude: <span id="lng-value">0</span></label>
82+
<input
83+
id="lng"
84+
type="range"
85+
min="-180"
86+
max="180"
87+
step="any"
88+
value="0"
89+
/>
6190
</fieldset>
62-
<fieldset>
63-
<label>Graticule:</label>
64-
<input id="graticule" type="checkbox">
91+
<fieldset class="conic-param-input">
92+
<label>Center Latitude: <span id="lat-value">30</span></label>
93+
<input
94+
id="lat"
95+
type="range"
96+
min="-90"
97+
max="90"
98+
step="any"
99+
value="30"
100+
/>
101+
</fieldset>
102+
<fieldset class="conic-param-input">
103+
<label
104+
>Southern Parallel Lat: <span id="lat1-value">30</span></label
105+
>
106+
<input
107+
id="lat1"
108+
type="range"
109+
min="-90"
110+
max="90"
111+
step="any"
112+
value="30"
113+
/>
114+
</fieldset>
115+
<fieldset class="conic-param-input">
116+
<label
117+
>Northern Parallel Lat: <span id="lat2-value">30</span></label
118+
>
119+
<input
120+
id="lat2"
121+
type="range"
122+
min="-90"
123+
max="90"
124+
step="any"
125+
value="30"
126+
/>
65127
</fieldset>
66128
<fieldset>
67129
<label>Show Debug Tiles:</label>
68-
<input id="debug" type="checkbox" checked=true>
130+
<input id="debug" type="checkbox">
69131
</fieldset>
70132
</div>
71-
<div id='map'></div>
133+
</details>
134+
</div>
72135

73136
<script src='../dist/mapbox-gl-dev.js'></script>
74137
<script src='../debug/access_token_generated.js'></script>
75138
<script>
76139

77-
let map;
78-
79-
const zooms = {
80-
albers: 3,
81-
lambertConformalConic: 3,
82-
winkelTripel: 1.2
83-
};
84-
const centers = {
85-
albers: [-122.414, 37.776],
86-
lambertConformalConic: [-122.414, 37.776]
87-
};
88-
89-
makeMap();
90-
91-
function makeMap() {
92-
if (map) map.remove();
93-
const el = document.getElementById('projName');
94-
const projection = el.options[el.selectedIndex].value;
95-
const zoom = zooms[projection] || 1;
96-
const center = centers[projection] || [0, 0];
97-
const styles = {
98-
streets: 'mapbox://styles/mapbox/streets-v10',
99-
satellite: 'mapbox://styles/mapbox/satellite-streets-v11'
100-
};
101-
const styleEl = document.getElementById('styleName');
102-
const styleName = styleEl.options[styleEl.selectedIndex].value;
103-
const style = styles[styleName];
104-
105-
map = new mapboxgl.Map({
106-
projection,
107-
container: 'map',
108-
zoom,
109-
center,
110-
style,
111-
hash: true
112-
});
113-
map.showTileBoundaries = true;
114-
addGraticule();
115-
}
116-
117-
map.on('click', function () {
118-
console.log('projection', map.getProjection());
119-
});
120-
121-
document.getElementById('projName').addEventListener('change', (e) => {
122-
const el = document.getElementById('projName');
123-
const projection = el.options[el.selectedIndex].value;
124-
const zoom = zooms[projection] || 1;
125-
const center = centers[projection] || [0, 0];
126-
map.jumpTo({center, zoom});
127-
map.setProjection(el.options[el.selectedIndex].value);
140+
const map = new mapboxgl.Map({
141+
container: 'map',
142+
hash: true,
143+
style: 'mapbox://styles/mapbox/streets-v11',
144+
zoom: 0,
145+
center: [0, 1],
146+
projection: {
147+
name: 'lambertConformalConic',
148+
center: [0, 30],
149+
parallels: [30, 30]
150+
}
128151
});
129152

130-
document.getElementById('styleName').addEventListener('change', (e) => {
131-
makeMap();
153+
const projectionInput = document.getElementById('projection');
154+
const styleInput = document.getElementById('style');
155+
const debugInput = document.getElementById('debug');
156+
const conicParamInputs =
157+
document.getElementsByClassName('conic-param-input');
158+
const lngInput = document.getElementById('lng');
159+
const lngValue = document.getElementById('lng-value');
160+
const latInput = document.getElementById('lat');
161+
const latValue = document.getElementById('lat-value');
162+
const lat1Input = document.getElementById('lat1');
163+
const lat1Value = document.getElementById('lat1-value');
164+
const lat2Input = document.getElementById('lat2');
165+
const lat2Value = document.getElementById('lat2-value');
166+
167+
projectionInput.addEventListener('change', (e) => {
168+
const isConic = ['albers', 'lambertConformalConic'].includes(
169+
e.target.value
170+
);
171+
172+
// Hide non-conic projection params
173+
for (const input of conicParamInputs) {
174+
input.style.display = isConic ? 'block' : 'none';
175+
}
176+
177+
const projection = isConic ? {
178+
name: e.target.value
179+
} : e.target.value;
180+
181+
map.setProjection(projection);
182+
183+
if (isConic) {
184+
const p = map.getProjection();
185+
lngInput.value = p.center[0];
186+
latInput.value = p.center[1];
187+
lat1Input.value = p.parallels[0];
188+
lat2Input.value = p.parallels[1];
189+
for (const [input, value] of inputs) {
190+
value.textContent = input.value;
191+
}
192+
}
132193
});
133194

134-
document.getElementById('graticule').addEventListener('change', (e) => {
135-
map.setPaintProperty('graticule', 'line-opacity', e.target.checked ? 1 : 0);
195+
styleInput.addEventListener('change', () => {
196+
map.setStyle('mapbox://styles/mapbox/' + styleInput.value);
136197
});
137-
138-
document.getElementById('debug').addEventListener('change', (e) => {
139-
map.showTileBoundaries = e.target.checked;
198+
debugInput.addEventListener('change', () => {
199+
map.showTileBoundaries = debugInput.checked;
140200
});
141201

142-
function addGraticule() {
143-
map.on('style.load', () => {
144-
const fc = {
145-
type: 'FeatureCollection',
146-
features: []
147-
};
148-
149-
for (let i = -170; i < 180; i += 10) {
150-
fc.features.push({
151-
type: 'Feature',
152-
geometry: {
153-
type: 'LineString',
154-
coordinates: [[i, -80], [i, 80]]
155-
}
156-
});
157-
}
158-
for (let i = -80; i < 80; i += 10) {
159-
fc.features.push({
160-
type: 'Feature',
161-
geometry: {
162-
type: 'LineString',
163-
coordinates: [[-180, i], [180, i]]
164-
}
165-
});
166-
}
167-
168-
map.addSource('graticule', {
169-
buffer: 0,
170-
type: 'geojson',
171-
data: fc
172-
});
173-
174-
map.addLayer({
175-
id: 'graticule',
176-
source: 'graticule',
177-
type: 'line',
178-
paint: {
179-
'line-width': 1,
180-
'line-color': '#aaa',
181-
'line-opacity': document.getElementById('graticule').checked ? 1 : 0
182-
}
202+
const inputs = [
203+
[lngInput, lngValue],
204+
[latInput, latValue],
205+
[lat1Input, lat1Value],
206+
[lat2Input, lat2Value]
207+
];
208+
209+
for (const [input, value] of inputs) {
210+
input.addEventListener('change', (e) => {
211+
value.textContent = e.target.value;
212+
map.setProjection({
213+
name: projectionInput.value,
214+
center: [Number(lngInput.value), Number(latInput.value)],
215+
parallels: [Number(lat1Input.value), Number(lat2Input.value)]
183216
});
184217
});
185218
}

0 commit comments

Comments
 (0)