MapLibre GL JS加载ArcGis Terrain3D地形

#MapLibre GL JS加载ArcGis Terrain3D地形#

很惭愧代码基本由Google Gemini生成,生成的原始代码在转换上有些错误,我给了提示它给出了修复代码片段。我将代码片段替换到原始代码去,一切工作正常。仅此而已!我甚至不知道以后没有AI助手我还能不能继续写代码。

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8" />
    <title>MapLibre GL 加载arcgis terrain3D</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <link href="https://unpkg.com/maplibre-gl@5.16.0/dist/maplibre-gl.css" rel="stylesheet" />
    <script src="https://unpkg.com/maplibre-gl@5.16.0/dist/maplibre-gl.js"></script>
    <script type="text/javascript" src="https://unpkg.com/lerc@latest/LercDecode.min.js"></script>
    <style>
        body { margin: 0; padding: 0; }
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
        .controls {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1;
            background: white;
            padding: 10px;
            border-radius: 4px;
            box-shadow: 0 0 10px rgba(0,0,0,0.2);
            font-family: sans-serif;
        }
    </style>
</head>
<body>

<div id="map"></div>
<div class="controls">
    <strong>MapLibre GL 加载arcgis terrain3D</strong><br>
    Google Gemini生成代码
</div>

<script>
    const map = new maplibregl.Map({
        container: 'map',
        // style: 'https://demotiles.maplibre.org/style.json', // 默认底图
        style: {
            "version": 8,
            // "glyphs": "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",
            "sources": {
                    "source-satellite": {
                    "type": "raster",
                    "tiles": ["https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png"],
                    "tileSize": 256,
                    "minzoom": 0,
                    "maxzoom": 20
                },
                "arcgisTerrainSource": {
                    "type": "raster-dem",
                    "tiles": ["arcgis-lerc://server.arcgisonline.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer/tile/{z}/{y}/{x}"],
                    "tileSize": 256,
                    "encoding": "mapbox"
                }
            },
            "layers": [
                {
                    "id": "base-layer-satellite",
                    "type": "raster",
                    "source": "source-satellite",
                    "layout": {
                        "visibility": "visible"
                    }
                }
            ]
        },
        center: [113.53658048252841, 37.70555767579111],
        zoom: 3
    });

    map.on('load', () => {

        // acgis地形图
        Lerc.load().then(()=>{
            /**
             * 自定义协议:将 ArcGIS LERC 转换为 MapLibre 识别的 DEM 数据
             */
            maplibregl.addProtocol('arcgis-lerc', async (params, abortController) => {
                const url = params.url.replace('arcgis-lerc://', 'https://');

                const t = await fetch(url);
                if (t.status == 200) {
                    const buffer = await t.arrayBuffer();
                    const decodedData = Lerc.decode(buffer);
                    const { width, height, pixels } = decodedData;
                    
                    // MapLibre 的地形要求:
                    // 1. 数据必须是经过 RGB 编码的图像,或者直接返回解码后的浮点数组(取决于版本)
                    // 2. 这里我们手动将浮点数转换为 MapLibre 预期的格式
                    const imageData = new Uint8ClampedArray(width * height * 4);
                    
                    for (let i = 0; i < pixels[0].length; i++) {
                        const elevation = pixels[0][i];
                        // 这里是一个简化的 Mapbox Terrain-RGB 编码逻辑
                        // 实际上 MapLibre 的某些版本支持更直接的返回,但这里使用通用转换
                        const value = Math.round((elevation + 10000) * 10);
                        imageData[i * 4] = (value >> 16) & 255;
                        imageData[i * 4 + 1] = (value >> 8) & 255;
                        imageData[i * 4 + 2] = value & 255;
                        imageData[i * 4 + 3] = 255;
                    }
                    const newImg = new ImageData(imageData, width, height);
                    const imageBitmap = await createImageBitmap(newImg);
                    return { data: imageBitmap };
                    // return { data: imageData, width, height };
                } else {
                    throw new Error(`Tile fetch error: ${t.statusText}`);
                }
            });

            map.setTerrain({
                source: 'arcgisTerrainSource',
                exaggeration: 1.0
            });
        });
        
    });
</script>

</body>
</html>
相关推荐
暗中讨饭的卫32 小时前
【ARCGIS】点生成以点为半径的圆圈
arcgis
POLITE32 小时前
Leetcode 236. 二叉树的最近公共祖先 (Day 17) JavaScript
linux·javascript·leetcode
雨季6662 小时前
构建 OpenHarmony 简易数字猜谜游戏:用随机与反馈打造轻量级互动体验
javascript·flutter·游戏·ui·自动化·dart
HWL56792 小时前
Vue Router中,传递参数的几种方式
前端·javascript·vue.js
晚霞的不甘2 小时前
Flutter for OpenHarmony 电商 App 搜索功能深度解析:从点击到反馈的完整实现
开发语言·前端·javascript·flutter·前端框架
Dragon Wu2 小时前
React Native MMKV完整封装
前端·javascript·react native·react.js
前端(从入门到入土)2 小时前
解决Webpack打包白屏报错问题l.a.browse is not a function
前端·javascript
Mr Xu_2 小时前
在 Vue 3 中集成 WangEditor 富文本编辑器:从基础到实战
前端·javascript·vue.js
EndingCoder2 小时前
Node.js 与 TypeScript:服务器端开发
前端·javascript·typescript·node.js