OpenLayers学习笔记-点位聚合

时间:2024-07-15 19:33:26

需求

用户点击行政区划等操作后,从后台获取区域内的点位数据,在地图上聚合显示。用户手动取消聚合,点位直接渲染在地图上。

实现过程

  1. 使用后台返回的点位数据,通过new ol.source.Vector({features})创建矢量数据源。
  2. 使用new ol.source.Cluster({source})创建聚合标注数据源,source参数设置为上一步创建的矢量数据源。
  3. 最后创建一个矢量图层new ol.layer.Vector({source})source参数设置为上一步创建的聚合标注数据源,再将矢量图层添加到地图上即可。
  4. 取消聚合可以通过两种方式实现。
    1. 方式一:通过设置两种不同的聚合样式:聚合数量大于1的样式和聚合数量等于1的样式。将聚合数量等于1的样式设置成点位的样式,来模拟不聚合的点位展示效果。
    2. 方式二:通过隐藏和显示图层实现。默认将点位图层也添加到地图上,在需要显示的时机,将聚合图层隐藏,显示点位图层。
  5. 可通过source.setDistance(number)设置聚合的像素,设置为0时,所有点位都不聚合,即可达到不聚合的效果。

知识点

  • new ol.style.Circle({radius, stroke, fill})创建一个圆形样式,可设置半径,描边颜色和填充颜色。
  • new ol.style.Text({text,fill,scale}),创建一个字体,可设置字体内容,颜色和缩放比例。
  • map.getView().animate({center, zoom})可跳转到指定的经纬度和显示层级。
  • 聚合点的feature有一个features属性,是一个存放着这个聚合下面的所有feature的数组,可通过feature.get('features')获得。
  • new ol.source.Cluster({distance, source})创建聚合标注数据源,通过source设置聚合的资源。通过distance设置聚合的距离。比如distance设置为150,表示如果2个点位之间的距离小于150px,即聚合成1个聚合点②。
  • new ol.layer.Vector({style})style参数可以是一个回调函数,函数的第一个参数是feature,可根据feature的不同,return不同的样式。
  • clusterLayer.getSource().setDistance(number)可在初始化聚合图层结束后,再次设置聚合距离,设置为0可实现不聚合的效果。
  • feature.get('features').length聚合点featurefeatures属性的length是此聚合点下点位的数量。
  • map.getView().getZoom()可获得当前地图的展示层级,有小数点。
  • layers.setVisible(true/false)可设置图层的显示和隐藏。
  • 通过map.on('moveend', () => {}可以监听地图移动事件,在地图平移和缩放结束后会触发此事件回调函数。可通过层级的变化,区分是平移还是缩放。
  • '#' + parseInt(Math.random() * 0xffffff).toString(16).padStart(6, '0')可随机生成16进制颜色值。
  • 在测试切换两种不同的实现不聚合的方式时,在地图层级小的时候,比如5级,切换后会感觉两种方式的点位不同。但如果将地图逐步放大,再次进行切换的时候,就不会有差异。最后发现是在聚合图层和直接渲染点位的图层中,重叠点位的处理不同,在聚合模式下,这个监控在上面,但是在直接渲染点位的图层中,这个监控却在下面。在地图层级小的时候,点位都聚集在了一起,重叠的数据非常多,导致切换时大量的点位层级变化,觉得异常。但当地图不断放大后,点位直接不重叠了,这时切换就感觉不到点位有什么变化了。
  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/8.2.0/ol.min.css" integrity="sha512-bc9nJM5uKHN+wK7rtqMnzlGicwJBWR11SIDFJlYBe5fVOwjHGtXX8KMyYZ4sMgSL0CoUjo4GYgIBucOtqX/RUQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
        <title>点位聚合</title>
        <style>
            * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        :root {
            --top-height: 50px;
        }
        html,
        body,
        #app,
        .app-map {
            height: 100%;
            height: 100%;
        }
        .app-btns {
            position: fixed;
            right: 10px;
            top: 10px;
            background-color: #fff;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .5);
            width: 210px;
            padding: 25px;
            text-align: center;
            border-radius: 5px;
            display: flex;
            flex-direction: column;
            z-index: 2;
        }
        .app-btns button {
            font-size: 18px;
            border: none;
            padding: 12px 10px;
            border-radius: 4px;
            color: #fff;
            background-color: #409eff;
            border-color: #409eff;
            cursor: pointer;
            border: 1px solid #dcdfe6;
            margin-bottom: 5px;
        }
        .app-btns button:hover {
            background: #66b1ff;
            border-color: #66b1ff;
        }
        .app-btns button.active {
            background-color: #07c160;
        }
        hr {
            margin: 20px 0;
        }
        .zoom {
            position: fixed;
            right: 10px;
            b