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

相关推荐
丷丩1 小时前
MapLibre GL JS第49课:用表达式创建渐变线
gis·可视化·地图·mapbox·maplibre gl js
丷丩21 小时前
MapLibre GL JS第47课:添加动画图标
javascript·gis·动画·mapbox·maplibre
丷丩1 天前
错误处理与容错机制:GeoAI-UP的降级策略设计
架构·gis·容错设计
丷丩2 天前
MapLibre GL JS第46课:用Markers添加自定义图标
gis·可视化·mapbox·maplibre gl js
duansamve2 天前
使用Python生成带20W有色立方体的矢量瓦片 MVT用于在Mapbox中加载的完整流程
mapbox
是潮汕的灿灿展吖3 天前
程序员开发的地图的选择
地图
丷丩3 天前
MapLibre GL JS第44课:生成并添加缺失图标
前端·javascript·gis·mapblibre gl js
丷丩6 天前
MapLibre GL JS第41课:向地图添加图标
前端·javascript·mapbox·maplibre gl js
GISBox6 天前
告别DEM数值枯燥:GISBox如何用颜色和等高线“翻译”地形
gis·等高线·地形·gisbox·geotiff·高度着色·地形高程可视化