MapLibre GL JS第22课:查看本地GeoJSON

📌 学习目标

  • 掌握查看本地GeoJSON的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

🎯 核心概念

无需服务器上传即可查看本地GeoJSON。

💻 完 整 代 码

代码示例

js 复制代码
const map = new maplibregl.Map({
    container: 'map',
    style: 'https://tiles.openfreemap.org/styles/bright',
    center: [-8.3226655, 53.7654751],
    zoom: 8
});

function handleFileSelect(evt) {
    const file = evt.target.files[0]; // 读取第一个选中的文件

    const reader = new FileReader();

    reader.onload = function (theFile) {
        // 解析为GeoJSON数据
        const geoJSONcontent = JSON.parse(theFile.target.result);

        // 添加到地图源
        map.addSource('uploaded-source', {
            'type': 'geojson',
            'data': geoJSONcontent
        });

        map.addLayer({
            'id': 'uploaded-polygons',
            'type': 'fill',
            'source': 'uploaded-source',
            'paint': {
                'fill-color': '#888888',
                'fill-outline-color': 'red',
                'fill-opacity': 0.4
            },
            // 过滤(多)多边形;如果还要显示线字符串
            // 或点,请添加更多具有不同过滤器的图层
            'filter': ['==', '$type', 'Polygon']
        });
    };

    // 以文本形式读取GeoJSON
    reader.readAsText(file, 'UTF-8');
}

document
    .getElementById('file')
    .addEventListener('change', handleFileSelect, false);

代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>View local GeoJSON</title>
    <meta property="og:description" content="无需服务器上传即可查看本地 GeoJSON。" />
    <meta property="og:created" content="2025-06-25" />
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css' />
    <script src='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js'></script>
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>
<body>
<style>
    #file {
        position: absolute;
        top: 0;
        left: 0;
    }
</style>
<div id="map"></div>
<input
    type="file"
    id="file"
    name="file"
    accept="application/geo+json,application/vnd.geo+json,.geojson"
/>
<script>
    const map = new maplibregl.Map({
        container: 'map',
        style: 'https://tiles.openfreemap.org/styles/bright',
        center: [-8.3226655, 53.7654751],
        zoom: 8
    });

    function handleFileSelect(evt) {
        const file = evt.target.files[0]; // 读取第一个选中的文件

        const reader = new FileReader();

        reader.onload = function (theFile) {
            // 解析为(geo)JSON
            const geoJSONcontent = JSON.parse(theFile.target.result);

            // 添加为地图数据源
            map.addSource('uploaded-source', {
                'type': 'geojson',
                'data': geoJSONcontent
            });

            map.addLayer({
                'id': 'uploaded-polygons',
                'type': 'fill',
                'source': 'uploaded-source',
                'paint': {
                    'fill-color': '#888888',
                    'fill-outline-color': 'red',
                    'fill-opacity': 0.4
                },
                // 过滤(多)多边形;如果还要显示线或点,
                // 添加更多具有不同过滤器的图层
                'filter': ['==', '$type', 'Polygon']
            });
        };

        // 以文本形式读取GeoJSON
        reader.readAsText(file, 'UTF-8');
    }

    document
        .getElementById('file')
        .addEventListener('change', handleFileSelect, false);
</script>
</body>
</html>

🔍 代码解析

1. 初始化地图

使用 new maplibregl.Map() 创建地图实例,配置基本参数。本示例中心点设置在爱尔兰附近。

2. 文件选择事件处理

监听 <input type="file">change 事件,获取用户选择的GeoJSON文件。

3. FileReader读取文件

使用 FileReader API 读取本地文件内容:

  • readAsText(): 以文本形式读取文件
  • onload: 文件读取完成后的回调

4. 解析并添加数据

将读取的文本解析为JSON,通过 map.addSource() 添加到地图,然后创建 fill 图层显示多边形。

5. Filter过滤

使用 ['==', '$type', 'Polygon'] 过滤只显示多边形要素。

⚙️ 参数说明

参数 类型 必填 说明
container string 地图容器ID
style string 地图样式URL
center number, number 初始中心点,默认0, 0
zoom number 初始缩放级别,默认0

FileReader 方法

方法 说明
readAsText(file, encoding) 以文本形式读取文件
readAsDataURL(file) 以Data URL形式读取文件
readAsArrayBuffer(file) 以二进制形式读取文件

🎨 效果说明

运行代码后:

  • 地图显示爱尔兰区域(中心点 -8.32°W, 53.77°N)
  • 页面顶部有文件选择按钮
  • 用户选择本地GeoJSON文件后,多边形以灰色填充(透明度40%)、红色边框显示
  • 用户可正常交互(拖拽、缩放、旋转)

💡 常 见 问 题

Q1: 如何支持多种几何类型?

A: 添加多个图层,使用不同filter:

javascript 复制代码
// 显示线
map.addLayer({
    'id': 'uploaded-lines',
    'type': 'line',
    'source': 'uploaded-source',
    'filter': ['==', '$type', 'LineString']
});
// 显示点
map.addLayer({
    'id': 'uploaded-points',
    'type': 'circle',
    'source': 'uploaded-source',
    'filter': ['==', '$type', 'Point']
});

Q2: 如何验证GeoJSON格式?

A: 使用 try-catch 包裹 JSON.parse,并检查必要字段:

javascript 复制代码
try {
    const geoJSONcontent = JSON.parse(theFile.target.result);
    if (!geoJSONcontent.type || !geoJSONcontent.features) {
        throw new Error('Invalid GeoJSON');
    }
} catch (e) {
    alert('无效的GeoJSON文件');
}

Q3: 如何清除已加载的图层?

A: 使用 map.removeLayer()map.removeSource()

javascript 复制代码
if (map.getLayer('uploaded-polygons')) {
    map.removeLayer('uploaded-polygons');
}
if (map.getSource('uploaded-source')) {
    map.removeSource('uploaded-source');
}

📝 练习任务

  1. 基础练习:修改多边形的填充颜色和边框样式
  2. 进阶挑战:添加对LineString和Point类型的支持
  3. 拓展思考:如何实现文件加载进度显示?

🌟 最佳实践

  1. 错误处理: 添加文件格式验证和异常捕获
  2. 用户体验: 提供加载状态反馈和错误提示
  3. 资源管理: 重新加载文件前清理旧的数据源和图层
  4. 文件类型限制 : 使用 accept 属性限制可选文件类型

🔗 延伸阅读


本文是MapLibre GL JS实践课程系列的一部分,欢迎关注收藏

相关推荐
油炸自行车1 小时前
Claude Code 错误:API Error: 400 Failed to deserialize the JSON body into the
开发语言·javascript·json·trae·claude code·api error 400
Front思2 小时前
AI前端工程师需要具备能力+
前端·人工智能·ai
ZC跨境爬虫4 小时前
跟着 MDN 学CSS day_29:(掌握文本与字体样式的核心艺术)
前端·css·ui·html·tensorflow
李子琪。5 小时前
网络空间安全深度实战:CSRF 漏洞原理剖析与基于 Token 的纵深防御体系构建(全栈实验报告)
前端·安全·csrf
冰暮流星5 小时前
javascript之history对象介绍
前端·笔记
IT_陈寒5 小时前
Vite热更新失灵?你可能漏了这个配置
前端·人工智能·后端
丷丩5 小时前
MapLibre GL JS第19课:实时更新要素
前端·javascript·gis·map·mapbox·maplibre gl js
Mr.Daozhi5 小时前
RAG 进阶实战:跑通 Demo 后我连续翻了 6 次车,逐一修复才真正可用(含 Gradio Web 版)
前端·数据库·langchain·大模型·gradio·rag·科研工具
哆来A梦没有口袋6 小时前
干货精讲 | 初级CSS面试高频考题
前端·css·面试