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实践课程系列的一部分,欢迎关注收藏

相关推荐
福兮说13 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
GreenTea13 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
科技观察哨14 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
niucloud-admin14 小时前
JAVA V6 多商户商城 开发文档——web前端
前端
颜进强14 小时前
16 · NestJS LifecycleEvents 生命周期事件:五个钩子、三条边界,和 rag-server 的优雅停机
前端·后端·ai编程
今年下半年16 小时前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
郑州光合科技余经理16 小时前
同城电商系统:库存变更怎么同步到订单
java·开发语言·前端·后端·uni-app·php·ai编程
前端snow18 小时前
ai agent --- DeepAgents 中间件
前端
data analyse 45618 小时前
报表能自定义的国内统计工具有哪些
前端·数据分析