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>
相关推荐
Hyyy3 小时前
普通前端续命周报——第1周
前端·javascript
GISer_Jing5 小时前
Three.JS渲染架构解读
java·javascript·架构
时寒的笔记6 小时前
day13~14核心案例某采招网
开发语言·javascript·ecmascript
智商不够_熬夜来凑6 小时前
【Picker】单选多选
前端·javascript·vue.js
米饭不加菜6 小时前
Typora 原生流程图语法完全指南(Flowchart.js)
前端·javascript·流程图
scan7247 小时前
langgraphy条件边
前端·javascript·html
用户938515635077 小时前
《JS 对象知识地图:10 个小节,从字面量到原型链全覆盖》
javascript
YAwu117 小时前
JavaScript this 底层机制剖析
前端·javascript
tedcloud1237 小时前
wifi-densepose部署教程:构建无线人体感知系统
服务器·javascript·网络·typescript·ocr