MapLibre GL JS第48课:用数据驱动属性样式化线

📌 学习目标

  • 掌握用数据驱动属性样式化线的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

🎯 核心概念

使用数据表达式创建线条颜色的可视化。

💻 完 整 代 码

代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Style lines with a data-driven property</title>
    <meta property="og:description" content="使用 line-color 的数据表达式创建可视化。" />
    <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>
<div id="map"></div>
<script>
    const map = new maplibregl.Map({
        container: 'map',
        style: 'https://tiles.openfreemap.org/styles/bright',
        center: [-122.48383155304096, 37.82882682974591],
        zoom: 16
    });

    map.on('load', () => {
        map.addSource('lines', {
            'type': 'geojson',
            'data': {
                'type': 'FeatureCollection',
                'features': [
                    {
                        'type': 'Feature',
                        'properties': {
                            'color': '#F7455D' // 红色
                        },
                        'geometry': {
                            'type': 'LineString',
                            'coordinates': [
                                [-122.4833858013153, 37.829607404976734],
                                [-122.4830961227417, 37.82932776098012],
                                [-122.4830746650696, 37.82932776098012],
                                [-122.48218417167662, 37.82889558180985],
                                [-122.48218417167662, 37.82890193740421],
                                [-122.48221099376678, 37.82868372835086],
                                [-122.4822163581848, 37.82868372835086],
                                [-122.48205006122589, 37.82801003030873]
                            ]
                        }
                    },
                    {
                        'type': 'Feature',
                        'properties': {
                            'color': '#33C9EB' // 蓝色
                        },
                        'geometry': {
                            'type': 'LineString',
                            'coordinates': [
                                [-122.48393028974533, 37.829471820141016],
                                [-122.48395174741744, 37.82940826466351],
                                [-122.48395174741744, 37.829412501697064],
                                [-122.48423874378203, 37.829357420242125],
                                [-122.48422533273697, 37.829361657278575],
                                [-122.48459815979002, 37.8293425906126],
                                [-122.48458743095398, 37.8293447091313],
                                [-122.4847564101219, 37.82932776098012],
                                [-122.48474299907684, 37.829331998018276],
                                [-122.4849334359169, 37.829298101706186],
                                [-122.48492807149889, 37.82930022022615],
                                [-122.48509705066681, 37.82920488676767],
                                [-122.48509168624878, 37.82920912381288],
                                [-122.48520433902739, 37.82905870855876],
                                [-122.48519897460936, 37.82905870855876],
                                [-122.4854403734207, 37.828594749716714],
                                [-122.48543500900269, 37.82860534241688],
                                [-122.48571664094925, 37.82808206121068],
                                [-122.48570591211319, 37.82809689109353],
                                [-122.4858346581459, 37.82797189627337],
                                [-122.48582661151886, 37.82797825194729],
                                [-122.4859634041786, 37.82788503534145],
                                [-122.48595803976059, 37.82788927246246],
                                [-122.48605459928514, 37.82786596829394]
                            ]
                        }
                    }
                ]
            }
        });
        map.addLayer({
            'id': 'lines',
            'type': 'line',
            'source': 'lines',
            'paint': {
                'line-width': 3,
                // 使用get表达式 (https://maplibre.org/maplibre-style-spec/expressions/#get)
                // 将线颜色设置为要素属性值。
                'line-color': ['get', 'color']
            }
        });
    });
</script>
</body>
</html>

🔍 代码解析

初始化地图

使用 new maplibregl.Map() 创建地图实例,配置基本参数。本示例的核心特色是展示如何使用数据驱动属性(data-driven property)为线条设置颜色。

关键配置项

  • container: 地图容器的 DOM 元素 ID
  • style : 使用 OpenStreetMap 亮色样式 https://tiles.openfreemap.org/styles/bright
  • center : 地图初始中心点 [-122.4838, 37.8288](美国旧金山区域)
  • zoom: 初始缩放级别为 16,显示街道级别视图

GeoJSON 数据源

javascript 复制代码
map.addSource('lines', {
    'type': 'geojson',
    'data': {
        'type': 'FeatureCollection',
        'features': [
            {
                'type': 'Feature',
                'properties': { 'color': '#F7455D' }, // 红色
                'geometry': { 'type': 'LineString', 'coordinates': [...] }
            },
            {
                'type': 'Feature',
                'properties': { 'color': '#33C9EB' }, // 蓝色
                'geometry': { 'type': 'LineString', 'coordinates': [...] }
            }
        ]
    }
});

数据驱动属性配置

javascript 复制代码
map.addLayer({
    'id': 'lines',
    'type': 'line',
    'source': 'lines',
    'paint': {
        'line-width': 3,
        'line-color': ['get', 'color'] // 使用 get 表达式获取属性值
    }
});

⚙️ 参数说明

参数 类型 必填 默认值 说明
container string - 地图容器元素的 ID
style string/object - 地图样式 URL 或内联样式对象
center number, number [0, 0] 初始中心点坐标
zoom number 0 初始缩放级别

get 表达式

参数 类型 说明
propertyName string 要获取的属性名称

line 图层 paint 属性

属性 类型 必填 默认值 说明
line-width number/expression 1 线条宽度(像素)
line-color string/expression #000000 线条颜色

🎨 效果说明

运行代码后,地图上会显示两条不同颜色的路径:

  • 红色路径 : 坐标从 [-122.4834, 37.8296][-122.4821, 37.8280],颜色为 #F7455D
  • 蓝色路径 : 坐标从 [-122.4839, 37.8295][-122.4861, 37.8279],颜色为 #33C9EB

数据驱动原理:

  • ['get', 'color'] 表达式会从每个要素的 properties 中读取 color 属性
  • 每条线根据自身的 color 属性值渲染对应的颜色
  • 支持鼠标拖拽、滚轮缩放等标准交互

💡 常 见 问 题

Q1: 什么是数据驱动属性?

A: 数据驱动属性允许根据 GeoJSON 要素的属性值动态设置图层样式。使用 get 表达式可以访问要素的 properties。

Q2: 除了颜色,还能驱动哪些属性?

A: 许多 paint 和 layout 属性都支持数据驱动,包括 line-widthline-opacitycircle-radiuscircle-color 等。

Q3: 如果属性不存在怎么办?

A: 如果 get 表达式找不到指定属性,会返回 null,图层会使用该属性的默认值或显示异常。建议使用 coalesce 提供默认值。

Q4: 可以使用其他表达式组合吗?

A: 可以。例如使用 match 表达式根据属性值返回不同颜色:

javascript 复制代码
'line-color': ['match', ['get', 'type'], 'road', '#FF0000', '#0000FF']

📝 练习任务

  1. 基础练习 :添加第三条路径,使用绿色 (#2ECC71)
  2. 进阶挑战:根据路径的长度动态设置线条宽度
  3. 拓展思考:如何实现根据属性值进行颜色渐变?

🌟 最佳实践

  1. 属性命名规范: 使用清晰的属性名称,便于维护
  2. 默认值处理 : 使用 coalesce 表达式为缺失属性提供默认值
  3. 表达式复用: 将复杂表达式提取为变量或函数
  4. 性能优化 : 对于大量要素,考虑使用 feature-state 而非频繁更新属性
  5. 颜色一致性: 保持颜色方案与整体设计风格一致
  6. 测试覆盖: 测试各种属性值和边界情况

🔗 延伸阅读


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

相关推荐
新中地GIS开发老师18 小时前
零基础WebGIS开发入门 | GeoJSON数据持久化
前端·javascript·gis·webgis·三维gis开发
一个有理想的摸鱼选手2 天前
在三维地球上以另一种视角感受巴威台风
前端·gis·ai编程
YouGIS顽石工坊2 天前
免费|中国1km分辨率逐月降水量数据集(1976-2025,50年600期):附Python/Matlab读取代码
gis·长时间序列·中国降雨量·逐月降水·1km分辨率·气候数据·delta降尺度
GISBox3 天前
告别逐点手动改属性:矢量组件批量编辑全流程
gis·矢量数据·属性表·服务发布·shp·gisbox·批量编辑
新中地GIS开发老师3 天前
地信职业百科④:GIS开发工程师
前端·数据库·gis·webgis·三维gis开发
两点王爷4 天前
一个快速加载面和多面数据的html测试页面(可以导出geojson数据文件)
前端·html·gis
YouGIS顽石工坊4 天前
Python GDAL实战:ASTER GDEM V003全国DEM高程数据处理(1123幅分幅合并→34省裁切,30m精度)
gis·遥感·dem·数据处理·空间数据库·数字高程模型·aster gdem
jinshw5 天前
自己实现GIS配图软件(一)
rust·开源·gis
zhz52147 天前
GIS项目中空间参考转换与MBTiles偏移:问题成因、解法与避坑
python·vue·gis
xiao5kou4chang6kai49 天前
GIS数据制备,空间分析与高级建模
arcgis·gis·空间数据