Created
September 27, 2019 12:02
-
-
Save andrewharvey/a0b56df5d605d86facc3da9723a9ef6e to your computer and use it in GitHub Desktop.
Mapbox GL JS look at elevation example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='utf-8' /> | |
<title>Look at Elevation</title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.2/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.2/mapbox-gl.css' rel='stylesheet' /> | |
<style> | |
body { margin:0; padding:0; } | |
#map { position:absolute; top:0; bottom:0; width:100%; } | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<script> | |
mapboxgl.accessToken = 'pk.eyJ1IjoiYWxhbnRnZW8tcHJlc2FsZXMiLCJhIjoiY2pxcmZ1cW1mMG1tcDN4bDVvYzA4MWg5MyJ9.7QtVj_0ythHwEg1n_zaRTQ'; | |
// workaround for viewing a point at an elevation | |
// this example uses a fill-extrusion to look at the top instead of the bottom of the extrusion | |
const center = [ 151.2015, -33.8620 ]; | |
const elevation = 1000; | |
const cameraPitch = 45; | |
const cameraBearing = 90; | |
const polygonRadius = 0.001; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/mapbox/streets-v11', | |
center: center, | |
zoom: 15, | |
pitch: 90 - cameraPitch, | |
bearing: 0, | |
antialias: true, | |
renderWorldCopies: false | |
}); | |
map.addControl(new mapboxgl.NavigationControl()); | |
map.on('load', function() { | |
// create a skyscraper | |
map.addLayer({ | |
'id': 'extrusion', | |
'type': 'fill-extrusion', | |
'source': { | |
'type': 'geojson', | |
'data': { | |
"type": "FeatureCollection", | |
"features": [ | |
{ | |
"type": "Feature", | |
"properties": {}, | |
"geometry": { | |
"type": "Polygon", | |
"coordinates": [ | |
[ | |
[ | |
center[0] - polygonRadius, | |
center[1] - polygonRadius | |
], | |
[ | |
center[0] + polygonRadius, | |
center[1] - polygonRadius | |
], | |
[ | |
center[0] + polygonRadius, | |
center[1] + polygonRadius | |
], | |
[ | |
center[0] - polygonRadius, | |
center[1] + polygonRadius | |
], | |
[ | |
center[0] - polygonRadius, | |
center[1] - polygonRadius | |
] | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
'paint': { | |
'fill-extrusion-color': '#dddddd', | |
'fill-extrusion-height': elevation, | |
'fill-extrusion-base': 0, | |
'fill-extrusion-opacity': 0.8 | |
} | |
}); | |
// in order to point the camera at an elevation we need to do two things: | |
// 1. find the projected point on the ground from the camera to the point at elevation and use this as our view center | |
// 2. find the appropriate camera zoom that will ensure the camera is far enough away from the point at elevation | |
// Part 1 | |
// given the camera pitch and elevation, find the projected distance along this bearing | |
const d = elevation / Math.tan(cameraPitch * Math.PI / 180) | |
// find the point on the ground relative to north and the center | |
const dx = d * Math.sin((cameraBearing) * Math.PI / 180) | |
const dy = d * Math.cos((cameraBearing) * Math.PI / 180) | |
const mercatorCenter = new mapboxgl.MercatorCoordinate.fromLngLat(center, 0); | |
const mercatorCenterProjected = new mapboxgl.MercatorCoordinate( | |
mercatorCenter.x + (dx * mercatorCenter.meterInMercatorCoordinateUnits()), | |
mercatorCenter.y + (-dy * mercatorCenter.meterInMercatorCoordinateUnits()), | |
0); | |
// move the camera to center on our projected point | |
map.jumpTo({ | |
center: mercatorCenterProjected.toLngLat(), | |
bearing: cameraBearing | |
}); | |
// Part 2 | |
// find the zoom which would position our camera at the center/elevation | |
const circumferenceAtEquator = 2 * Math.PI * 6378137; | |
// elevation = (circumferenceAtEquator / Math.pow(2, zoom) / 2) / Math.tan(map.transform._fov / 2) | |
const zoom = Math.log2(circumferenceAtEquator / (2 * elevation * Math.tan(map.transform._fov / 2))) | |
map.setZoom(zoom - 2); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment