Mapbox GL JS 是一款高性能的开源矢量地图渲染库,其表达式系统(Expressions) 是实现数据驱动样式、要素过滤、交互控制的核心。== 作为最基础且高频使用的比较表达式,用于判断两个值是否严格相等 ,是解锁 Mapbox 高级样式定制的必备知识点。本文将从核心概念、语法、实战场景、进阶用法到常见误区,全面讲解 == 表达式的使用。
一、== 表达式核心概念
1.1 严格类型相等
== 表达式的比较规则与 JavaScript 的 === 完全一致:
- 不仅要求值相等 ,还要求运行时类型完全一致 (如数字
5≠ 字符串"5",布尔值true≠ 数字1); - 若解析阶段就能确定两个值类型不同(如
["==", 1, "1"]),Mapbox 会直接抛出解析错误 (而非运行时返回false)。
1.2 语法格式
== 表达式支持两种语法(官方定义):
javascript
// 基础版:无本地化比较
["==", value1, value2]: boolean
// 进阶版:带本地化字符串比较(collator 参数)
["==", value1, value2, collator]: boolean
参数说明:
value1/value2:可以是字面量 (数字、字符串、布尔值)、属性引用 (["get", "属性名"])、其他表达式的返回值;collator(可选):本地化配置对象,用于控制多语言场景下的字符串比较规则(如忽略大小写、重音)。
二、基础使用场景
== 表达式最核心的用途是要素过滤 和数据驱动样式,以下结合实战示例讲解。
前置准备
所有示例需先初始化 Mapbox 地图,并替换为自己的 Access Token(从 Mapbox 官网 注册获取):
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Mapbox == 表达式示例</title>
<script src="https://api.mapbox.com/mapbox-gl-js/v3.4.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.4.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; }
#map { width: 100vw; height: 100vh; }
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = '你的 Mapbox Access Token'; // 替换为自己的 Token
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [116.4074, 39.9042], // 北京坐标
zoom: 14
});
</script>
</body>
</html>
2.1 场景1:过滤地图要素
通过 filter 属性结合 == 表达式,可精准控制图层显示/隐藏特定要素。
示例:自定义 POI 数据,仅显示类型为 restaurant(餐厅)的要素:
javascript
map.on('load', () => {
// 模拟 POI 地理数据
const poiData = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: { type: 'Point', coordinates: [116.4074, 39.9042] },
properties: { type: 'restaurant', name: '北京饭店' }
},
{
type: 'Feature',
geometry: { type: 'Point', coordinates: [116.4084, 39.9052] },
properties: { type: 'coffee', name: '星巴克' }
},
{
type: 'Feature',
geometry: { type: 'Point', coordinates: [116.4094, 39.9062] },
properties: { type: 'park', name: '天安门广场' }
}
]
};
// 1. 添加数据源
map.addSource('poi-source', {
type: 'geojson',
data: poiData
});
// 2. 添加图层,仅显示餐厅(核心:== 过滤)
map.addLayer({
id: 'poi-restaurant',
type: 'circle',
source: 'poi-source',
paint: {
'circle-radius': 10,
'circle-color': '#ff0000' // 红色标记餐厅
},
filter: ['==', ['get', 'type'], 'restaurant'] // 判定 type 属性是否等于 "restaurant"
});
});
2.2 场景2:数据驱动样式
通过 == 结合 case 表达式,可根据要素属性值动态设置样式(如不同类型 POI 用不同颜色):
javascript
// 替换上述示例的 addLayer 部分
map.addLayer({
id: 'poi-all',
type: 'circle',
source: 'poi-source',
paint: {
'circle-radius': 10,
'circle-color': [
'case', // 多条件 == 判断
['==', ['get', 'type'], 'restaurant'], '#ff0000', // 餐厅:红
['==', ['get', 'type'], 'coffee'], '#00ff00', // 咖啡:绿
['==', ['get', 'type'], 'park'], '#0000ff', // 公园:蓝
'#999999' // 默认:灰
]
}
});
三、进阶用法:Collator 本地化字符串比较
默认的字符串比较是「严格匹配」(区分大小写、重音),但多语言场景下(如法语重音、中文拼音混合),需通过 collator 参数实现本地化比较。
3.1 Collator 核心配置
| 配置项 | 类型 | 说明 | 默认值 |
|---|---|---|---|
locale |
字符串/数组 | 语言标签(如 zh-CN、en-US、fr) |
- |
case-sensitive |
布尔值 | 是否区分大小写 | true |
accent-sensitive |
布尔值 | 是否区分重音(如 é 和 e) |
true |
3.2 实战示例:多语言字符串匹配
示例1:法语场景忽略重音
匹配 café(带重音)和 cafe(无重音)为相等:
javascript
map.on('load', () => {
// 法语咖啡数据
const frenchData = {
type: 'FeatureCollection',
features: [
{ type: 'Feature', geometry: { type: 'Point', coordinates: [2.3522, 48.8566] }, properties: { name: 'café' } },
{ type: 'Feature', geometry: { type: 'Point', coordinates: [2.3622, 48.8666] }, properties: { name: 'cafe' } }
]
};
map.addSource('french-source', { type: 'geojson', data: frenchData });
// 图层过滤:忽略重音匹配 "café"
map.addLayer({
id: 'french-cafe',
type: 'circle',
source: 'french-source',
paint: { 'circle-radius': 10, 'circle-color': '#00ffff' },
filter: [
'==',
['get', 'name'],
'café',
{ locale: 'fr', accent-sensitive: false } // 法语 + 忽略重音
]
});
// 点击跳转至巴黎
map.jumpTo({ center: [2.3522, 48.8566], zoom: 14 });
});
示例2:中文场景忽略大小写
匹配名称时忽略大小写(适用于中英文混合场景):
javascript
filter: [
'==',
['get', 'name'],
'北京饭店',
{ locale: 'zh-CN', case-sensitive: false }
]
四、常见误区与注意事项
4.1 类型不一致导致判断失效
== 是严格类型比较,以下场景会返回 false 或直接报错:
javascript
// 错误1:数字 id(123)≠ 字符串 "123"
["==", ["get", "id"], "123"]
// 错误2:解析阶段类型已知不同,直接报错
["==", 1, "1"]
// 正确做法:统一类型后比较
["==", ["to-string", ["get", "id"]], "123"] // 数字转字符串
4.2 Collator 仅对字符串有效
若 value1/value2 不是字符串(如数字、布尔值),collator 参数会被直接忽略,无任何效果。
4.3 语言标签格式错误
locale 需使用标准 BCP 47 语言标签(如 zh-CN 而非 zh,en-US 而非 en),否则本地化规则可能不生效。
4.4 混淆 == 和 =
==:用于比较判断(如 filter、case 表达式);=:用于赋值(如 layout/paint 属性的静态值)。
五、完整实战示例
整合过滤、数据驱动样式、本地化比较,实现交互性地图:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Mapbox == 表达式完整实战</title>
<script src="https://api.mapbox.com/mapbox-gl-js/v3.4.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.4.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; }
#map { width: 100vw; height: 100vh; }
.controls { position: absolute; top: 20px; left: 20px; background: white; padding: 10px; border-radius: 5px; }
</style>
</head>
<body>
<div id="map"></div>
<div class="controls">
<button id="showRestaurant">显示餐厅</button>
<button id="showAll">显示所有POI</button>
<button id="showFrenchCafe">显示法语咖啡</button>
</div>
<script>
mapboxgl.accessToken = '你的 Mapbox Access Token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [116.4074, 39.9042],
zoom: 14
});
map.on('load', () => {
// 1. 中文 POI 数据
const poiData = {
type: 'FeatureCollection',
features: [
{ type: 'Feature', geometry: { type: 'Point', coordinates: [116.4074, 39.9042] }, properties: { type: 'restaurant', name: '北京饭店', id: 123 } },
{ type: 'Feature', geometry: { type: 'Point', coordinates: [116.4084, 39.9052] }, properties: { type: 'coffee', name: '星巴克', id: 456 } },
{ type: 'Feature', geometry: { type: 'Point', coordinates: [116.4094, 39.9062] }, properties: { type: 'park', name: '天安门广场', id: 789 } }
]
};
map.addSource('poi-source', { type: 'geojson', data: poiData });
// 2. 法语咖啡数据
const frenchData = {
type: 'FeatureCollection',
features: [
{ type: 'Feature', geometry: { type: 'Point', coordinates: [2.3522, 48.8566] }, properties: { name: 'café' } },
{ type: 'Feature', geometry: { type: 'Point', coordinates: [2.3622, 48.8666] }, properties: { name: 'cafe' } }
]
};
map.addSource('french-source', { type: 'geojson', data: frenchData });
// 3. 中文 POI 图层(数据驱动样式)
map.addLayer({
id: 'poi-chinese',
type: 'circle',
source: 'poi-source',
paint: {
'circle-radius': 10,
'circle-color': [
'case',
['==', ['get', 'type'], 'restaurant'], '#ff0000',
['==', ['get', 'type'], 'coffee'], '#00ff00',
['==', ['get', 'type'], 'park'], '#0000ff',
'#999'
]
},
filter: ['all'] // 默认显示所有
});
// 4. 法语咖啡图层(本地化比较)
map.addLayer({
id: 'poi-french',
type: 'circle',
source: 'french-source',
paint: { 'circle-radius': 10, 'circle-color': '#00ffff' },
filter: ['==', ['get', 'name'], 'café', { locale: 'fr', accent-sensitive: false }],
layout: { visibility: 'none' } // 默认隐藏
});
// 5. 按钮交互
document.getElementById('showRestaurant').onclick = () => {
map.setFilter('poi-chinese', ['==', ['get', 'type'], 'restaurant']);
};
document.getElementById('showAll').onclick = () => {
map.setFilter('poi-chinese', ['all']);
};
document.getElementById('showFrenchCafe').onclick = () => {
map.setLayoutProperty('poi-french', 'visibility', 'visible');
map.jumpTo({ center: [2.3522, 48.8566], zoom: 14 });
};
});
</script>
</body>
</html>
六、总结
== 表达式是 Mapbox 表达式系统的基础核心,核心价值在于严格类型的相等判断,广泛应用于:
- 图层要素过滤(
filter属性); - 数据驱动样式(
case/match表达式结合); - 本地化字符串匹配(
collator参数)。
使用时需重点注意类型一致性 ,避免解析错误或判断失效;针对多语言场景,合理配置 collator 可大幅提升地图的国际化适配能力。掌握 == 表达式后,可进一步学习 !=/</> 等比较表达式,实现更复杂的地图逻辑。