ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MapLibre Native 样式表达式教程:4 个核心表达式控制地图颜色、大小与显隐

MapLibre Native 样式表达式教程:4 个核心表达式控制地图颜色、大小与显隐

MapLibre Native 样式表达式教程:4 个核心表达式控制地图颜色、大小与显隐

【免费下载链接】maplibre-nativeMapLibre Native - Interactive vector tile maps for iOS, Android and other platforms.项目地址: https://gitcode.com/GitHub_Trending/ma/maplibre-native

你往地图上丢了五百个定位点,结果密密麻麻糊成一团。想让重要的先冒头、次要的往后排,又不想去改数据字段?MapLibre Native 的样式表达式能按属性值和缩放级别,自动重算每个要素该长什么样。

一句话讲透:样式表达式是给要素写 if-else 🎯

先建个最直白的心智模型:样式表达式就是贴在每个要素身上的 if-else。你写下"数据字段 → 视觉属性"的映射规则,渲染引擎对每一个要素求一次值,输出它真实的颜色、半径或透明度。它不是命令"画一个红点",而是描述"什么条件下该是什么",剩下的一律交给引擎逐个算。

想让它随缩放变、随属性变、随条件变,下面这张表就是你能用的积木。

样式表达式速查表

名称用途最小示例
get读要素的某个属性字段["get", "temperature"]
literal给一个确定的值或数组["literal", ["a", "b"]]
interpolate在区间内平滑过渡(颜色/数值)["interpolate", ["linear"], ["zoom"], 10, 1, 16, 4]
step跨阈值时跳一档["step", ["get", "magnitude"], 2, 4, 6]
case多个条件按顺序取第一个为真的["case", ["==", ["get", "status"], 1], "red", "grey"]
match按离散值精确匹配["match", ["get", "class"], "trunk", 8, 2]
zoom取当前缩放级别(内置函数)["zoom"]

这些积木能单独用,也能一层套一层。下面挑三个高频场景,直接把代码搬进你的paint。

三个高频场景实战

circle-radius 表达式按震级分档

半径随震级分档,大震级一眼就能看到,小震级退成小点。

"circle-radius": [ "step", ["get", "magnitude"], 2, 4, 6, 6, 10 ]

为什么这样写:震级是人按"5 级以上才危险"来感知的,step分档比连续插值更符合直觉,两档之间不用纠结中间值。

interpolate 插值表达式给温度区间配色

气温图层里,颜色随温度从冷到热连续过渡,不用手动切十几种色。

"circle-color": [ "interpolate", ["linear"], ["get", "temperature"], -10, "#1a9850", 20, "#fee08b", 40, "#d73027" ]

为什么这样写:interpolate在两个 stop 之间做线性插值,温度是连续量,过渡自然;中间再补几个 stop 就能把色带掰成你想要的形状。

line-width 表达式叠加道路等级与缩放

主干道比小路粗,而且越放大越粗,两条规则叠在一起生效。

"line-width": [ "step", ["zoom"], ["match", ["get", "class"], "trunk", 6, "street", 3, 1], 16, 8 ]

为什么这样写:step的默认值本身又是一个表达式,所以"按缩放调宽"和"按等级调粗"能嵌在一层里,这正是表达式嵌套的典型用法。

新手最容易踩的 3 个坑 ⚠️

漏它,引擎只能两手一摊:不知道输出啥。下面三处都是编译期就能抓到的错。

  • interpolate漏插值类型错误:["interpolate", ["zoom"], 10, 1, 20, 4]正确:["interpolate", ["linear"], ["zoom"], 10, 1, 20, 4]第二个参数必须显式写["linear"](或["exponential", 基底]、["cubic-bezier", ...]),缺了直接编译失败。

  • case漏默认分支错误:["case", ["==", ["get", "status"], 1], "red"]正确:["case", ["==", ["get", "status"], 1], "red", "grey"]最后一个参数是无条件兜底值,所有条件都不满足时用它,漏了引擎没有出口。

  • 取缩放级别写成get错误:["get", "zoom"]正确:["zoom"]zoom是内置函数不是属性,["get", "zoom"]永远读不到东西。

三个坑都指向同一件事:表达式对结构极敏感,差一个参数就废。写完拿测试用例对一对最稳。

三步跑通第一个动态样式

第 1 步,把仓库拉到本地:

git clone https://gitcode.com/GitHub_Trending/ma/maplibre-native

第 2 步,保存下面这份style.json(含 sources、layers、paint 三块,可直接粘贴):

{ "version": 8, "sources": { "quakes": { "type": "geojson", "data": "assets/quakes.geojson" } }, "layers": [ { "id": "quakes", "type": "circle", "source": "quakes", "paint": { "circle-radius": ["step", ["get", "magnitude"], 2, 4, 6, 6, 10], "circle-color": ["interpolate", ["linear"], ["get", "magnitude"], 2, "#ffff00", 7, "#d73027"] } } ] }

第 3 步,加载它:Android 侧mapView.getMapAsync { map -> map.setStyle(url) },iOS 侧mapView.loadStyle(MLNStyle(url: url)),引擎会按表达式逐个要素重算视觉。

延伸阅读

想系统翻规范、找现成范例,这两处最值得逛:

  • 样式规范与概念文档:docs/mdbook/src/design/
  • 表达式测试用例(每种表达式都有输入输出对照):metrics/integration/expression-tests/
  • 渲染测试样例(各种表达式写进 style.json 的真实样子):metrics/integration/render-tests/

【免费下载链接】maplibre-nativeMapLibre Native - Interactive vector tile maps for iOS, Android and other platforms.项目地址: https://gitcode.com/GitHub_Trending/ma/maplibre-native

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进