mapbox-gl | 2.3 热力图

简述

本节讲述热力图,讲解的案例用的是官方示例,主要讲解热力图的这几个配置项

热力图,是以特殊的高亮形式(渐变色带)对数据的聚合状态进行表达。这或许表达的并不准确。举一个场景例子,我们有全球地震发生的地点和级别,以点的形式标记在地图上,为了更直观的表现地震发生的频率,可以采用热力图表达。

在GIS学科里,有一类方法叫做插值,如克里金插值等,他们会根据不同的算法进行插值,形成的结果其实和热力图类似(或者说一样),而影响插值结果的有很多,简单来讲有距离(半径)和权重。

距离 权重是本文需要注意的两点

示例

代码

function addHeatMap(map) {
  // 本示例为官方示例改动而成
  map.addSource("earthquakes", {
    type: "geojson",
    // 数据为mapbox官方数据
    // 可能访问不到或者跨域,本地测试时可以直接下下来
    data: "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
  });

  map.addLayer(
    {
      id: "earthquakes-heat",
      type: "heatmap",
      source: "earthquakes",
      maxzoom: 9,
      paint: {
        // 根据频率和属性大小增加热力图权重
        "heatmap-weight": [
          "interpolate",
          ["linear"],
          ["get", "mag"],
          0,
          0,
          6,
          1,
        ],
        // 根据缩放级别增加热力图权重
        // heatmap-intensity 是热力图权重的乘数
        "heatmap-intensity": ["interpolate", ["linear"], ["zoom"], 0, 1, 9, 3],
        // 色带
        "heatmap-color": [
          "interpolate",
          ["linear"],
          ["heatmap-density"],
          0,
          "rgba(33,102,172,0)",
          0.2,
          "rgb(103,169,207)",
          0.4,
          "rgb(209,229,240)",
          0.6,
          "rgb(253,219,199)",
          0.8,
          "rgb(239,138,98)",
          1,
          "rgb(178,24,43)",
        ],
        // 根据缩放级别调整热力图半径
        "heatmap-radius": ["interpolate", ["linear"], ["zoom"], 0, 2, 9, 20],
        // 透明度
        "heatmap-opacity": ["interpolate", ["linear"], ["zoom"], 7, 1, 9, 0],
      },
    },
    "waterway-label"
  );
  // 添加圆图层,叠加效果更好
  map.addLayer(
    {
      id: "earthquakes-point",
      type: "circle",
      source: "earthquakes",
      minzoom: 7,
      paint: {
        "circle-radius": [
          "interpolate",
          ["linear"],
          ["zoom"],
          7,
          ["interpolate", ["linear"], ["get", "mag"], 1, 1, 6, 4],
          16,
          ["interpolate", ["linear"], ["get", "mag"], 1, 5, 6, 50],
        ],
        "circle-color": [
          "interpolate",
          ["linear"],
          ["get", "mag"],
          1,
          "rgba(33,102,172,0)",
          2,
          "rgb(103,169,207)",
          3,
          "rgb(209,229,240)",
          4,
          "rgb(253,219,199)",
          5,
          "rgb(239,138,98)",
          6,
          "rgb(178,24,43)",
        ],
        "circle-stroke-color": "white",
        "circle-stroke-width": 1,
        "circle-opacity": ["interpolate", ["linear"], ["zoom"], 7, 0, 8, 1],
      },
    },
    "waterway-label"
  );
  map.flyTo({
    center: [-120, 50],
    zoom: 2,
  });
}

示例逻辑

  1. 请求地震数据并添加为source
  2. 添加热力图(heatmap)
  3. 添加圆图(circle)

第一步为addSource,第三步是圆图层,这两步不做讲解,重点关注热力图这段

示例代码解析

  map.addLayer(
    {
      id: "earthquakes-heat",
      type: "heatmap",
      source: "earthquakes",
      maxzoom: 9,
      paint: {
        // 根据频率和属性大小增加热力图权重
        "heatmap-weight": [
          "interpolate",
          ["linear"],
          ["get", "mag"],
          0,
          0,
          6,
          1,
        ],
        // 根据缩放级别增加热力图权重
        // heatmap-intensity 是热力图权重的乘数
        "heatmap-intensity": ["interpolate", ["linear"], ["zoom"], 0, 1, 9, 3],
        // 色带
        "heatmap-color": [
          "interpolate",
          ["linear"],
          ["heatmap-density"],
          0,
          "rgba(33,102,172,0)",
          0.2,
          "rgb(103,169,207)",
          0.4,
          "rgb(209,229,240)",
          0.6,
          "rgb(253,219,199)",
          0.8,
          "rgb(239,138,98)",
          1,
          "rgb(178,24,43)",
        ],
        // 根据缩放级别调整热力图半径
        "heatmap-radius": ["interpolate", ["linear"], ["zoom"], 0, 2, 9, 20],
        // 透明度
        "heatmap-opacity": ["interpolate", ["linear"], ["zoom"], 7, 1, 9, 0],
      },
    },
    "waterway-label"
  );

heatmap-weight

热力图权重,默认为1,这个属性更多是要和字段联系起来,最后将字段值归一化(变成0~1),这是上文所说的权重
如果不设置这个属性,就会让热力图只和距离相关。

  "heatmap-weight": [
    "interpolate",

    ["linear"],

    ["get", "mag"],
    0,

    0,
    6,
    1,
  ],

这里有一个之前没讲过的表达式 interpolate, 是插值的意思,而后面的 [‘linear’] 是插值的方式,整体为线性插值,还有另外几种方式,这里不作详解(作为入门,学会这个就可以应对绝大部分业务场景)

[`interpolate`,['linear'],["get",属性字段],值1,效果值1,值2,效果值2,·····]

在我们的示例中,先获取为mag字段的值(这份地震数据中,mag字段值的范围是06),以06归一化,为了方便理解,我将它转化为js代码(下面代码不能代表真实的底层逻辑)

属性值 /(值2 - 值1) * ( 效果值2 - 效果值1 )+ 效果值1
// 假如 mag 字段值为 2
2 / (6-0) + (1 - 0) + 0  // 0.333
// 假如 mag 字段值为 3
3 / (6-0) + (1 - 0) + 0 // 0.5

heatmap-intensity

heatmap-weight类似,也是对权重的控制,但我更愿意叫它为权重系数

  "heatmap-intensity": ["interpolate", ["linear"], ["zoom"], 0, 1, 9, 3],

可以看到这个字段的设置也使用了线性渐变的表达式,但和之前不同的是,这里并没有用[“get”,属性字段]的方式获取Feature属性,因为这里的zoom是mapbox自身的属性,不需要通过get形式获取,get是获取Feature的写法。

这里有一个之前没接触的概念,mapbox(map)自身属性,zoom值的是地图当前的缩放级别,我们可以利用它实现一些动态效果,比如之前的例子中,我们绘制了不同颜色的面,但并不会随着地图缩放产生变化,如果我们用线性渐变和zoom对颜色进行控制,那么就会实现随着缩放变化面的颜色。

在这个例子中,使用线性渐变和zoom变化权重系数,这会让一个数据在不同缩放级别下有不同的权重,从而达到美观的效果

heatmap-color

热力图颜色,热力图颜色需要一个色带,所以至少需要两种颜色,然后通过线性插值供程序使用。

  "heatmap-color": [
    "interpolate",

    ["linear"],

    ["heatmap-density"],
    0,

    "rgba(33,102,172,0)",
    0.2,
    "rgb(103,169,207)",
    0.4,
    "rgb(209,229,240)",
    0.6,
    "rgb(253,219,199)",
    0.8,
    "rgb(239,138,98)",
    1,
    "rgb(178,24,43)",
  ],

这里同样使用了线性插值,并且用了另一个mapbox(map)自带的属性,heatmap-density,指热力图密度,即热力图图层插值计算后的结果(每一个像素点,值域0~1),示例中渐变用了六种颜色。注意,插值表达式写法没有默认值(case,match都有默认值)

heatmap-radius

热力图半径(距离),这是开头说的距离,每一个数据点与指定半径内其他数据点进行计算,单位是像素。

"heatmap-radius": ["interpolate", ["linear"], ["zoom"], 0, 2, 9, 20],

同样用了线性渐变,此处不作解释。

heatmap-opacity

热力图透明度,当透明度为0时便隐藏了

 "heatmap-opacity": ["interpolate", ["linear"], ["zoom"], 7, 1, 9, 0],

同样用了线性渐变,此处不作解释。

示例总结

heatmap-weight连接数据字段mag作为权重,heatmap-color设置热力图色带,再以heatmap-radius设置热力图半径,heatmap-intensity设置热力图系数,heatmap-opacity设置热力图透明度。通过对zoom线性插值的使用让热力图在不同级别有不同的表现。

总结

本节讲述了热力图几个重要的属性及其效果,同时对interpolate线性插值表达式进行了讲解,下节讲fill-extrusion的应用

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYpK6Nue' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片