expressions
本文回答:vjmap 样式表达式(get / case / match / interpolate / step / feature-state / zoom)实战。
一、表达式是什么
任何 paint / layout / filter 的值都可以写成表达式(一个 JSON 数组,第一个元素是操作符)。
// "line-width": 2
// 改为:按缩放级别变宽
"line-width": ["interpolate", ["linear"], ["zoom"], 10, 1, 16, 5]
二、常用操作
| 类别 | 典型 |
|---|---|
| Lookup | ["get", "name"], ["has", "color"], ["at", 0, arr], ["length", arr], ["properties"], ["id"], ["geometry-type"] |
| Feature-state | ["feature-state", "hover"] |
| Decision | ["case", cond1, val1, cond2, val2, defaultVal], ["match", input, val1, out1, val2, out2, default] |
| Ramps | ["interpolate", ["linear"], ["zoom"], 0, a, 10, b], ["step", ["zoom"], a, 5, b, 10, c] |
| Comparison | ["==", ..], ["!=", ..], [">", ..], ["<=", ..], ["in", ..] |
| Boolean | ["all", a, b], ["any", a, b], ["!", cond] |
| Arithmetic | ["+", a, b], ["-", a, b], ["*", a, b], ["/", a, b], ["%", a, b], ["^", a, b], ["abs", x], ["min", ...], ["max", ...] |
| Type | ["to-string", x], ["to-number", x], ["to-boolean", x], ["to-color", x], ["typeof", x] |
| String | ["concat", a, b], ["upcase", s], ["downcase", s] |
| Color | ["rgb", r, g, b], ["rgba", r, g, b, a], ["to-color", "#f00"] |
| Let/Var | ["let", "x", 1, ["+", ["var", "x"], 2]] |
三、典型用法
按属性变色
"fill-color": ["get", "color"]
按属性分类
"fill-color": [
"match", ["get", "type"],
"road", "#0af",
"building", "#f80",
"park", "#8c0",
"#aaa" // default
]
按 zoom 插值
"circle-radius": [
"interpolate", ["linear"], ["zoom"],
8, 2,
14, 6,
18, 12
]
按值插值(热力等级)
"fill-color": [
"interpolate", ["linear"], ["get", "heat"],
0, "#00f",
50, "#0f0",
100, "#f00"
]
step 分段
"line-color": [
"step", ["zoom"],
"#aaa", // zoom < 10
10, "#888", // 10 <= zoom < 14
14, "#333" // zoom >= 14
]
条件(hover 状态)
"fill-color": [
"case",
["boolean", ["feature-state", "hover"], false], "#f00",
["get", "color"]
]
组合过滤 filter
filter: ["all",
["==", ["geometry-type"], "Polygon"],
[">=", ["to-number", ["get", "h"]], 50]
]
四、feature-state 用法
feature-state 不是数据的属性,而是运行时附加的状态。
// feature 的 id 必须是整数或可以转整数的字符串
map.setFeatureState({ source: "states", id: 54 }, { hover: true });
// 样式中
"fill-opacity": [
"case",
["boolean", ["feature-state", "hover"], false], 1,
0.5
]
// 移除
map.removeFeatureState({ source: "states", id: 54 });
feature-state 只能用在 paint(支持数据驱动)的属性里。
五、zoom 与 properties 的差别
["zoom"]:只能在interpolate/step的输入里;不能直接参与其他算术。违规写法(如["+", ["zoom"], 1]直接给line-width)不抛异常,而是走map.on("error")事件:layers.*.paint.*: "zoom" expression may only be used as input to...——静默失败,调试时记得挂 error 监听。["get", "name"]:任何地方都能用。["heatmap-density"]:只能在heatmap-color属性里。
六、样式规范约束
- paint 随小数 zoom 插值(
*-pattern、line-dasharray例外,只按整数 zoom 求值)。 - layout 多数按瓦片的整数 zoom 求值;但
text-size/icon-size的 zoom 表达式会在小数 zoom 上插值(4.2→4.6 字号会连续变化)。
七、后端表达式(CAD 栅格样式)
CAD 栅格图渲染在后端,不是样式表达式,而是服务端表达式语法:
gOutColorRed := 255; // 输出红色分量
gOutColorGreen := 0;
gOutColorBlue := 0;
gOutColorAlpha := 255; // 透明度分量 0~255(不是 0~1,写 1.0 几乎全透明)
变量前缀:gIn* 是输入(层名、颜色、线型…),gOut* 是输出。详见 svrStyleVar / expr.md。
前端通过 map.updateStyle(svc, { expression: "..." }) 写入(内部 svc.cmdUpdateStyle + 刷新瓦片;单独调 svc.cmdUpdateStyle 地图不会刷新,还得 map.changeSourceTiles(svc.rasterTileUrl()))。
八、调试表达式
// 控制台会报错;开 Chrome DevTools
// 常用 console.log(JSON.stringify(style, null, 2)) 查看当前生效的样式
九、常见坑
- 类型错误:
["==", ["get", "n"], 1]里 n 如果是字符串会不等;显式to-number。 - filter 中不支持 interpolate:只 paint/layout 支持 zoom 插值,filter 不行。
- feature-state 在 layout 不生效:只能用在 paint。
- id 不是整数 → feature-state 不生效;
generateId: true让 GeoJSON source 自动生成 id。