更多精彩内容尽在dt.sim3d.cn,关注公众号【sky的数孪技术】,技术交流、源码下载请添加VX:digital_twin123
使用mapboxgl 3.0版本,根据 AWS 地形图块的高程值制作等高线,源码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Contours</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.0/mapbox-gl.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
function generateContours() {
let steps = ['step',
['raster-value']
]
for (let i = guiInstance.minElev + guiInstance.stepInterval; i <= guiInstance.maxElev; i++) {
if (Math.abs(guiInstance.referenceElev - i) % guiInstance.stepInterval === 0) {
steps.push('transparent')
steps.push(i)
} else if (Math.abs((guiInstance.referenceElev + guiInstance.stepWidth) - i) % guiInstance.stepInterval === 0) {
steps.push(guiInstance.contourColor)
steps.push(i)
}
}
steps.push('transparent')
map.setPaintProperty('aws-terrain-raster', 'raster-color', steps)
}
let guiObject = function () {
this.referenceElev = 0;
this.minElev = 0;
this.maxElev = 8900;
this.stepInterval = 200;
this.stepWidth = 50;
this.contourColor = '#452d1f';
this.contourOpacity = 0.75;
};
let guiInstance = new guiObject();
let gui = new dat.GUI();
let params = gui.addFolder("Contour Options")
params.open();
params.add(guiInstance, "referenceElev", 0, 8900, 1).name("参考高程").onChange(function (value) {
generateContours()
});
let minElev = params.add(guiInstance, "minElev", 0, 8899, 1).name("最小高程").onChange(function (value) {
if (value >= guiInstance.maxElev) {
guiInstance.maxElev = value + 1;
maxElev.updateDisplay();
}
generateContours()
});
let maxElev = params.add(guiInstance, "maxElev", 1, 8900, 1).name("最大高程").onChange(function (value) {
if (value <= guiInstance.minElev) {
guiInstance.minElev = value - 1;
minElev.updateDisplay();
}
generateContours()
});
let stepInterval = params.add(guiInstance, "stepInterval", 20, 2000, 20).name("等高线间距").onChange(function (value) {
if (value <= guiInstance.stepWidth) {
guiInstance.stepWidth = value - 10;
stepWidth.updateDisplay();
}
generateContours()
});
let stepWidth = params.add(guiInstance, "stepWidth", 10, 1000, 10).name("等高线宽度").onChange(function (value) {
if (value >= guiInstance.stepInterval) {
guiInstance.stepInterval = value + 20;
stepInterval.updateDisplay();
}
generateContours()
});
params.addColor(guiInstance, "contourColor").name("等高线颜色").onChange(function (value) {
generateContours()
});
params.add(guiInstance, "contourOpacity", 0, 1).name("等高线透明度").onChange(function (value) {
map.setPaintProperty('aws-terrain-raster', 'raster-opacity', value)
});
mapboxgl.accessToken = 'pk.eyJ1IjoiZGt3aWVucyIsImEiOiJjbHJ3aWZxZWcwaWVnMnFvMnlxdjMwOWJjIn0.0JZciL5p5aT8AWSoIhgH6A';
const map = new mapboxgl.Map({
container: "map",
center: {
lat: 45,
lng: -123
},
zoom: 6,
attributionControl: false
});
map.addControl(new mapboxgl.ScaleControl({
maxWidth: 200,
unit: 'metric'
}));
map.on('load', () => {
map.addSource('mapbox-dem', {
'type': 'raster-dem',
'url': 'mapbox://mapbox.mapbox-terrain-dem-v1',
'tileSize': 512,
'maxzoom': 14
});
map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 2.5 });
map.addSource('aws-terrain-raster', {
"type": "raster",
"minzoom": 1,
"maxzoom": 18,
"tiles": ["https://elevation-tiles-prod.s3.amazonaws.com/v2/terrarium/{z}/{x}/{y}.png"],
"tileSize": 256,
"attribution": "<a href='https://registry.opendata.aws/terrain-tiles/' target='_blank'>AWS Terrain Tiles</a>"
})
map.addLayer({
id: 'aws-terrain-raster',
source: 'aws-terrain-raster',
type: 'raster',
paint: {
'raster-color': [
'step',
['raster-value'],
'#000098', 1,
'transparent'
],
'raster-color-mix': [
255 * 256.0,
255 * 1.0,
255 * 0.00390625,
-32768.0
],
'raster-color-range': [0, 8900],
'raster-opacity': 0.75,
'raster-resampling': 'nearest'
}
})
generateContours(guiInstance.elev)
})
</script>
</body>
</html>