MapLibre GL JS第58课:用全局状态过滤图层符号

📌 学习目标

  • 掌握用全局状态过滤图层符号的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

🎯 核心概念

使用全局状态过滤图层符号。

💻 完 整 代 码

<!DOCTYPE html>
<html lang='en'>
<head>
    <title>Filter layer symbols using global state</title>
    <meta property="og:description" content="使用 setGlobalStateProperty() 根据用户输入过滤图层符号。" />
    <meta property="og:created" content="2006-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%;
        }

        fieldset {
            position: absolute;
            top: 10px;
            left: 10px;
            background-color: white;
            padding: 10px;
        }
    </style>
</head>

<body>
    <div id='map'></div>
    <fieldset>
        Filter by type
        <select name="type">
            <option value="" selected>All</option>
            <option value="lift">Aerial lift</option>
            <option value="railway">Cable railway</option>
        </select>
    </fieldset>
</body>

<script>
    const map = new maplibregl.Map({
        container: 'map',
        style: 'https://demotiles.maplibre.org/style.json',
        center: [9.0679, 45.8822],
        zoom: 9
    });

    map.on('load', () => {
        map.addSource('railways_and_lifts', {
            type: 'geojson',
            data: 'https://maplibre.org/maplibre-gl-js/docs/assets/funicolares-and-funivias-como.json'
        });

        map.addLayer({
            id: 'railways_and_lifts_labels',
            type: 'symbol',
            source: 'railways_and_lifts',
            layout: {
                'text-field': '{name}',
                'text-font': ['Open Sans Semibold'],
                'text-offset': [0, 1],
                'text-anchor': 'top'
            },
            paint: {
                'text-color': '#000000',
                'text-halo-color': '#ffffff',
                'text-halo-width': 2
            },
            filter: [
                'case',
                ['==', ['to-string', ['global-state', 'type']], ''],
                true,
                ['==', ['get', 'type'], ['global-state', 'type']]
            ]
        });
        map.addLayer({
            type: 'circle',
            id: 'railways_and_lifts_points',
            source: 'railways_and_lifts',
            paint: {
                'circle-radius': 5,
                'circle-color': '#000000',
            },
            filter: [
                'case',
                ['==', ['to-string', ['global-state', 'type']], ''],
                true,
                ['==', ['get', 'type'], ['global-state', 'type']]
            ]
        });

        const select = document.querySelector('select[name="type"]');
        map.setGlobalStateProperty('type', select.value);

        select.addEventListener('change', (e) => {
            const value = e.target.value;
            map.setGlobalStateProperty('type', value);
        });
    });
</script>

</html>

🔍 代码解析

1. 初始化地图

使用 new maplibregl.Map() 创建地图实例,配置了意大利科莫湖区域,展示索道和缆车数据。

2. 关键配置项

  • setGlobalStateProperty(): 设置全局状态属性,可被所有图层的表达式访问
  • global-state表达式: 在filter中读取全局状态值
  • case表达式: 根据全局状态值动态过滤图层内容

⚙️ 参数说明

参数类型必填说明
setGlobalStateProperty(key, value)method-设置全局状态属性
global-stateexpression在表达式中读取全局状态值
to-stringexpression将值转换为字符串进行比较
caseexpression条件分支表达式

🎨 效果说明

在这里插入图片描述

运行代码后,地图显示意大利科莫湖区域的索道和缆车位置。页面顶部有一个下拉选择框,用户可以选择:

  • All: 显示所有类型的索道和缆车
  • Aerial lift: 只显示架空索道
  • Cable railway: 只显示缆索铁路

选择不同选项时,地图会实时更新显示的图层内容,无需重新加载数据。

💡 常 见 问 题

Q1: 全局状态没有生效怎么办?
A: 检查以下几点:

  1. 确认使用 map.setGlobalStateProperty() 设置了全局状态
  2. 确认在filter表达式中正确使用 ['global-state', 'key']
  3. 检查全局状态的键名是否一致

Q2: 全局状态支持哪些数据类型?
A: 全局状态支持字符串、数字、布尔值等基本类型:

map.setGlobalStateProperty('type', 'lift');      // 字符串
map.setGlobalStateProperty('zoom', 10);          // 数字
map.setGlobalStateProperty('enabled', true);      // 布尔值

Q3: 如何清除全局状态属性?
A: 使用 deleteGlobalStateProperty() 方法:

map.deleteGlobalStateProperty('type');

📝 练习任务

  1. 基础练习:添加更多过滤选项,如按名称过滤
  2. 进阶挑战:创建多个过滤条件的组合筛选功能
  3. 拓展思考:如何实现全局状态的持久化存储?
  4. 综合实践:创建一个完整的图层过滤面板,支持多条件筛选

🌟 最佳实践

  1. 状态管理: 使用全局状态集中管理跨图层的共享配置
  2. 性能优化: 全局状态变化会触发图层重新渲染,避免频繁更新
  3. 默认值处理: 在case表达式中提供默认分支处理未设置状态的情况
  4. 类型转换: 使用to-string/to-number确保类型一致性
  5. 事件监听: 结合事件监听器实现响应式UI交互

🔗 延伸阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丷丩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值