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>
相关推荐
UIUV19 小时前
node:child_process spawn 模块学习笔记
javascript·后端·node.js
烛阴20 小时前
Three.js 零基础入门:手把手打造交互式 3D 几何体展示系统
javascript·webgl·three.js
颜酱20 小时前
单调栈:从模板到实战
javascript·后端·算法
_AaronWong1 天前
Electron 实现仿豆包划词取词功能:从 AI 生成到落地踩坑记
前端·javascript·vue.js
JohnYan1 天前
工作笔记-CodeBuddy应用探索
javascript·ai编程·aiops
wuhen_n1 天前
双端 Diff 算法详解
前端·javascript·vue.js
光影少年1 天前
说说闭包的理解和应用场景?
前端·javascript·掘金·金石计划
爱勇宝1 天前
别再混用了!import.meta.env 与 process.env 的本质差异一次讲透
前端·javascript·vue.js
路修远i1 天前
基于SSE的AI对话流式结构
前端·javascript
摸鱼的春哥1 天前
春哥的Agent通关秘籍13:实现RAG查询
前端·javascript·后端