Skip to content

Instantly share code, notes, and snippets.

@andrewharvey
Created September 27, 2019 12:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewharvey/a0b56df5d605d86facc3da9723a9ef6e to your computer and use it in GitHub Desktop.
Save andrewharvey/a0b56df5d605d86facc3da9723a9ef6e to your computer and use it in GitHub Desktop.
Mapbox GL JS look at elevation example
<!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