mapbox 表达式

604 阅读4分钟

mapbox Expressions

Mapbox 中,可以将任何布局属性绘制属性过滤器的值定义为JSON数组结构的表达式,其基本形式如下:

[
    "<操作符>",
    <操作数1>,
    <操作数2>,
    ...
]

操作符

操作符是数组的第一个元素,常见的操作符:

1. 数据访问

  • get: 返回 Feature 属性的值,类型取决于属性的值(可以是数字、字符串、布尔值等)。
  • type: 返回属性值的类型,类型为字符串(如 "number""string""boolean" 等)。

2. 数学运算

  • +-*/ : 返回运算的结果。
  • abssqrtsincostan: 返回函数的结果。
  • acosasinatan: 返回反三角函数的结果。
  • log2: 返回以 2 为底的对数。
  • round: 返回四舍五入的结果。

3. 字符串操作

  • concat: 返回拼接后的字符串。
  • upcasedowncase: 返回转换大小之后的字符串。
  • to-string: 返回将值转换为字符串的结果。

4. 条件判断

  • case: 返回满足条件的值。
  • match: 返回匹配的值。
  • coalesce: 返回第一个非空值,类型取决于输入值的类型。

5. 插值与分段

  • interpolate: 返回插值的结果,类型为数字。
  • step: 返回分段的结果,类型为数字。

6. 数字格式化

  • number-format:返回格式化后的数字,字符串类型。

7. 其他

  • let: 返回定义的变量表达式的结果,类型取决于变量表达式的值。
  • has: 返回属性是否存在[boolean]。

操作数

操作数可以是常量值、嵌套的表达式、配置对象[{}包裹用于格式化最终的值]。

1. 常量值

单个常量操作数

当操作数只有一个的时候,通常以以下方式出现
text-font:["Arial Unicode MS Regular"];

[
    "+",
    ["get", "value"],
    10  // 单个数字常量
]

或者在嵌套中使用

[
    "case",
    ["==", ["get", "type"], "A"], "red",  // 单个字符串常量
    ["==", ["get", "type"], "B"], "blue",
    "green"
]
多个常量操作数

多个映射常量对通常用于分段或插值场景,定义一系列输入值和对应的输出值。这种格式常见于 interpolatestep 操作符,以及 matchcase 条件表达式。

interpolate操作符

  • 输入值和输出值必须成对出现
  • 插值类型不可省略
[
    "interpolate",
    <插值类型>,
    <输入变量>,
    <输入值1>,<输出值1>,
    <输入值2>,<输出值2>,
]

step操作符

  • 值阶梯型非线性渐变,不可添加插值类型
  • 默认值不能省略
[
    "step",
    <输入变量>,
    <默认值>,
    <输入值1>,<输出值1>,
    <输入值2>,<输出值2>,
]

match操作符

  • match 操作符主要用于匹配离散的值(如字符串或数字),而不是连续的值(如缩放级别)
  • 输入表达式常见:["get","property_name"]["feature-state","property_name"]["id"]
[
    "match",
    <输入表达式>,
    <值1>, <输出值1>,
    <值2>, <输出值2>,
    ...成对
    <默认值>
]
//feature数据里面添加properties
[{
    "type": "Feature",
    "geometry": { "type": "Point", "coordinates": [0, 0] },
    "properties": { "type": "A" }
}]
//layer的paint设置:
 "circle-color": [
    "match",
    ["get", "type"],  // 获取 type 属性
    "A", "red",       // 如果 type 为 "A",返回 "red"
    "B", "blue",      // 如果 type 为 "B",返回 "blue"
    "gray"            // 默认值
],
//也可以设置:
 "paint": {
    "circle-color": [
        "match",
        ["feature-state", "highlight"],  // 获取 highlight 状态属性
        true, "red",                     // 如果 highlight 为 true,返回 "red"
        false, "blue",                   // 如果 highlight 为 false,返回 "blue"
        "gray"                           // 默认值
    ],
    "circle-radius": 6
}
//id的情况,先给source的feature添加id属性
 {
    "type": "Feature",
    "id": 1,
    "geometry": { "type": "Point", "coordinates": [0, 0] },
    "properties": {}
}
//然后可以在layer中使用
 "paint": {
    "circle-color": [
        "match",
        ["id"],  // 获取 id 属性
        1, "red",  // 如果 id 为 1,返回 "red"
        2, "blue", // 如果 id 为 2,返回 "blue"
        "gray"     // 默认值
    ],
    "circle-radius": 6
}

2. 嵌套的表达式

即表达式相互嵌套,如下:

[
    "case",
    ["==", ["get", "type"], "A"], "red",  // 嵌套的比较表达式
    ["==", ["get", "type"], "B"], "blue",
    "green"
]

3. 配置对象

当表达式计算出结果之后,配置对象对这个结果进行再次格式化,通常放最后,例如:

//将数字保留一位有效位
[
    "number-format",
    ["get", "population"],
    { "min-fraction-digits": 1, "max-fraction-digits": 1 }
]
//将字符串格式化
//从GEOJSON特征的properties中获取population属性的值转换成字符串
//将字符串格式化成美国英语的数字格式1234567->1,234,567
[
    "to-string",
    ["get", "population"],
    { "locale": "en-US", "type": "number" }
]

测试用例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Mapbox Interpolate Example</title>
    <link
      href="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css"
      rel="stylesheet"
    />
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }
      #map {
        width: 100vw;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      mapboxgl.accessToken =
        "pk.eyJ1Ijoiaml5ZXdlbiIsImEiOiJjbG5qeW9nZTIxbmtlMm1ybHVzMW04djh5In0._6aML1rN-1KVGurR9aIVCg"; // 替换为你的 Mapbox Access Token
      const map = new mapboxgl.Map({
        container: "map",
        style: "mapbox://styles/mapbox/streets-v12",
        center: [120, 30],
        zoom: 10,
      });
      map.on("load", () => {
        map.addSource("single-point", {
          type: "geojson",
          data: {
            type: "FeatureCollection",
            features: [
              {
                type: "Feature",
                geometry: {
                  type: "Point",
                  coordinates: [120, 30],
                },
                properties: {},
              },
            ],
          },
        });
        map.addLayer({
          id: "point-layer",
          type: "circle",
          source: "single-point",
          paint: {
            "circle-color": "#ff0000",
            "circle-radius": ["step", ["zoom"], 5, 5, 10, 10, 20, 15, 30],
          },
        });
        map.on("zoom", () => {
          const currentZoom = map.getZoom();
          console.log(currentZoom);
        });
      });
    </script>
  </body>
</html>

更多详情参见官网:
Mapbox GL JS 表达式快速入门 |帮助 |地图盒
表达式 |Mapbox 样式规范 |Mapbox 文档 |地图盒