OpenLayers实现点要素图层的聚合显示的方法

目录
  • 1、前言
  • 2、点要素图层的聚合
  • 3、聚合特殊处理一
  • 4、聚合特殊处理二
  • 5.、结语

1、前言

在很多情况下,点要素图层中的要素数量可能会成百上千,这时候如果不做任何处理直接加载到地图上不仅会使用户视觉体验下降,而且也会造成地图界面的卡顿。下面这段代码创建了1000个随机点进行显示:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <title>OpenLayers</title>
    <style>
        html, body, #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <link href="libs/ol/ol.css" rel="stylesheet" />
    <script src="libs/ol/ol.js"></script>
</head>
<body>
    <div id="map"></div>

    <script>
        // 随机创建1000个要素
        var source = new ol.source.Vector();
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.00 + Math.random(), 30.00 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.01 + Math.random(), 30.01 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.02 + Math.random(), 30.02 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.03 + Math.random(), 30.03 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.04 + Math.random(), 30.04 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }

        // 创建图层
        var layer = new ol.layer.Vector({
            source: source,
            style: function (feature, resolution) {
                var style = new ol.style.Style({
                    image: new ol.style.Icon({
                        src: 'img/location.png'
                    })
                })
                return style;
            }
        });

        // 创建地图
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                layer
            ],
            view: new ol.View({
                projection: 'EPSG:4326',
                center: [120, 30],
                zoom: 10,
                minZoom: 5,
                maxZoom: 14
            })
        });
    </script>
</body>
</html>

运行结果如下图所示:

这么多点挤在一起,是不是感觉很恶心?一般来说,如果一个点要素图层中的点数量很多,我们就会采取图层聚合的方式对其进行处理。但需要注意:图层聚合只对点要素图层有效,对线和面图层无效

2、点要素图层的聚合

openlayers中,图层聚合的一般步骤如下:

  • 创建要素
  • 创建数据源添加要素
  • 创建聚合数据源,设置聚合的距离
  • 创建图层,将数据源设置为聚合数据源
  • 创建地图,添加聚合图层

图层聚合代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <title>OpenLayers</title>
    <style>
        html, body, #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <link href="libs/ol/ol.css" rel="stylesheet" />
    <script src="libs/ol/ol.js"></script>
</head>
<body>
    <div id="map"></div>

    <script>
        // 随机创建1000个要素
        var source = new ol.source.Vector();
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.00 + Math.random(), 30.00 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.01 + Math.random(), 30.01 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.02 + Math.random(), 30.02 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.03 + Math.random(), 30.03 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.04 + Math.random(), 30.04 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }

        // 聚合
        var cluster = new ol.source.Cluster({
            source: source,
            distance: 100
        })

        // 创建图层
        var layer = new ol.layer.Vector({
            source: cluster,
            style: function (feature, resolution) {
                var size = feature.get('features').length;
                var style = new ol.style.Style({
                    image: new ol.style.Circle({
                        radius: 30,
                        stroke: new ol.style.Stroke({
                            color: 'white'
                        }),
                        fill: new ol.style.Fill({
                            color: 'blue'
                        })
                    }),
                    text: new ol.style.Text({
                        text: size.toString(),
                        fill: new ol.style.Fill({
                            color: 'white'
                        })
                    })
                })
                return style;
            }
        });

        // 创建地图
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                layer
            ],
            view: new ol.View({
                projection: 'EPSG:4326',
                center: [120, 30],
                zoom: 10,
                minZoom: 5,
                maxZoom: 14
            })
        });
    </script>
</body>
</html>

运行结果如下图所示:

3、聚合特殊处理一

上面的代码虽然实现了点要素图层的聚合,但其实存在着一个问题:地图缩放层级最大时仍然保持着聚合效果,如下图所示:

一般来说,当某处只有一个点时就应该取消聚合效果,这时候我们就需要在style: function (feature, resolution)这个回调函数里做文章了,代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <title>OpenLayers</title>
    <style>
        html, body, #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <link href="libs/ol/ol.css" rel="stylesheet" />
    <script src="libs/ol/ol.js"></script>
</head>
<body>
    <div id="map"></div>

    <script>
        // 随机创建1000个要素
        var source = new ol.source.Vector();
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.00 + Math.random(), 30.00 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.01 + Math.random(), 30.01 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.02 + Math.random(), 30.02 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.03 + Math.random(), 30.03 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.04 + Math.random(), 30.04 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }

        // 聚合
        var cluster = new ol.source.Cluster({
            source: source,
            distance: 100
        })

        // 创建图层
        var layer = new ol.layer.Vector({
            source: cluster,
            style: function (feature, resolution) {
                var size = feature.get('features').length;
                if (size == 1) {
                    return new ol.style.Style({
                        image: new ol.style.Icon({
                            src: 'img/location.png'
                        })
                    })
                }
                else {
                    return new ol.style.Style({
                        image: new ol.style.Circle({
                            radius: 30,
                            stroke: new ol.style.Stroke({
                                color: 'white'
                            }),
                            fill: new ol.style.Fill({
                                color: 'blue'
                            })
                        }),
                        text: new ol.style.Text({
                            text: size.toString(),
                            fill: new ol.style.Fill({
                                color: 'white'
                            })
                        })
                    })
                }
            }
        });

        // 创建地图
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                layer
            ],
            view: new ol.View({
                projection: 'EPSG:4326',
                center: [120, 30],
                zoom: 10,
                minZoom: 5,
                maxZoom: 14
            })
        });
    </script>
</body>
</html>

运行结果如下图所示:

其实这个效果实现起来很简单,核心代码就是:var size = feature.get('features').length;,如果size>1,则返回聚合样式,反之则返回图片样式。

4、聚合特殊处理二

在上面的代码中,我把地图的最大缩放层级设置为14,这也就导致了一个问题:当地图缩放到最大层级时,还有很多点保持着聚合效果。有时候用户可能会要求:当地图缩放到最大层级时,取消全部聚合效果。如果要实现这个功能,我们就需要对地图事件进行监听了,代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <title>OpenLayers</title>
    <style>
        html, body, #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <link href="libs/ol/ol.css" rel="stylesheet" />
    <script src="libs/ol/ol.js"></script>
</head>
<body>
    <div id="map"></div>

    <script>
        // 随机创建1000个要素
        var source = new ol.source.Vector();
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.00 + Math.random(), 30.00 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.01 + Math.random(), 30.01 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.02 + Math.random(), 30.02 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.03 + Math.random(), 30.03 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }
        for (var i = 1; i <= 200; i++) {
            var coordinates = [120.04 + Math.random(), 30.04 + Math.random()];
            var feature = new ol.Feature(new ol.geom.Point(coordinates));
            source.addFeature(feature);
        }

        // 聚合
        var cluster = new ol.source.Cluster({
            source: source,
            distance: 100
        })

        // 创建图层
        var layer = new ol.layer.Vector({
            source: cluster,
            style: function (feature, resolution) {
                var size = feature.get('features').length;
                if (size == 1) {
                    return new ol.style.Style({
                        image: new ol.style.Icon({
                            src: 'img/location.png'
                        })
                    })
                }
                else {
                    return new ol.style.Style({
                        image: new ol.style.Circle({
                            radius: 30,
                            stroke: new ol.style.Stroke({
                                color: 'white'
                            }),
                            fill: new ol.style.Fill({
                                color: 'blue'
                            })
                        }),
                        text: new ol.style.Text({
                            text: size.toString(),
                            fill: new ol.style.Fill({
                                color: 'white'
                            })
                        })
                    })
                }
            }
        });

        // 创建地图
        var map = new ol.Map({
            target: 'map',
            layers: [
                new ol.layer.Tile({
                    source: new ol.source.OSM()
                }),
                layer
            ],
            view: new ol.View({
                projection: 'EPSG:4326',
                center: [120, 30],
                zoom: 10,
                minZoom: 5,
                maxZoom: 14
            })
        });

        // 监听地图分辨率改变事件
        map.getView().on('change:resolution', function (event) {
            if (map.getView().getZoom() == map.getView().getMaxZoom()) {
                cluster.setDistance(0);
            }
            else {
                cluster.setDistance(100);
            }
        })
    </script>
</body>
</html>

运行结果如下图所示:

这个效果的实现也很简单,只需要监听当前地图的分辨率变化事件,如果当前缩放层级已经是最大层级,则将聚合的距离设置为0即可。

5.、结语

在要素数量很多的情况下,我们应该考虑对其进行聚合处理,这样不仅提升了用户的使用感受,而且也可以避免界面卡顿。其实在上面的代码中,我对change:resolution事件进行了监听,你也可以换成另一个事件——moveend,代码如下所示:

map.on('moveend', function (event) {
    if (map.getView().getZoom() == map.getView().getMaxZoom()) {
        cluster.setDistance(0);
    }
    else {
        cluster.setDistance(100);
    }
});

moveend事件进行监听也可以实现相同的效果,因为无论是地图的缩放、平移都会触发该事件。

到此这篇关于OpenLayers实现点要素图层的聚合显示的方法的文章就介绍到这了,更多相关OpenLayers 点要素图层的聚合显示内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • OpenLayers实现图层切换控件

    OpenLayers并没有封装图层切换的控件,所以我们需要自己来实现图层控件. 自定义图层切换控件的原理很简单:显示某个图层时,将其他图层隐藏. 完整代码: layerSwitch.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="wi

  • Openlayers+EasyUI Tree动态实现图层控制

    本文实例为大家分享了Openlayers+EasyUI Tree动态实现图层控制的具体代码,供大家参考,具体内容如下 功能介绍 主要功能 根据openlayers3.0与easyUI tree 功能实现图层显隐控制功能,达到子节点选择实现单个图层的显隐,父节点选择实现所有图层的显隐. 页面展示 主要代码 HTML+CSS #xuanfu1 { position: absolute; top: 50px; right: 40px; background-color: rgba(134,149,23

  • OpenLayers3实现图层控件功能

    本文实例为大家分享了OpenLayers3实现图层控件的具体代码,供大家参考,具体内容如下 1. 前言 在实际应用中,我们将加载到地图容器中的图层通过图层显示的控件功能,来显示加载的图层,便于用户查看与操作,OpenLayers 3 中并没有提供类似的图层控件,但是他的 API 却提供了该功能的相关接口,我们可以通过调用相关的接口,实现该功能. 2. 实现思路 (1)新建一个网页,参考前面的文章加载OSM瓦片图层的方法,加载OSM瓦片.MapQuest 影像.JSON 与KML 格式的矢量图.

  • OpenLayers实现点要素图层的聚合显示的方法

    目录 1.前言 2.点要素图层的聚合 3.聚合特殊处理一 4.聚合特殊处理二 5..结语 1.前言 在很多情况下,点要素图层中的要素数量可能会成百上千,这时候如果不做任何处理直接加载到地图上不仅会使用户视觉体验下降,而且也会造成地图界面的卡顿.下面这段代码创建了1000个随机点进行显示: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="tex

  • Android编程实现压缩图片并加载显示的方法

    本文实例讲述了Android编程实现压缩图片并加载显示的方法.分享给大家供大家参考,具体如下: 解析: 图片压缩的关键就是 options.inSampleSize = scale; 如果scale > 0,表示图片进行了压缩 /** * 压缩图片 * @author chen.lin * */ public class LoadImageActivity extends Activity implements OnClickListener { private Button mBtnLoad;

  • PHP读取txt文本文件并分页显示的方法

    本文实例讲述了PHP读取txt文本文件并分页显示的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <?php     session_start();     if (empty($page)) {$page=1;}     if (isset($_GET['page'])==TRUE) {$page=$_GET['page']; } ?> <html> <head> <meta http-equiv="Content-Type&q

  • jQuery焦点控制图层展示延迟隐藏的方法

    本文实例讲述了jQuery焦点控制图层展示延迟隐藏的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> </head> <body> <b id="button"

  • js父页面与子页面不同时显示的方法

    本文实例讲述了js父页面与子页面不同时显示的方法,可实现打开一个页面后,父页面DISABLE,在子页面关闭后,父页面ENABLE.分享给大家供大家参考.具体方法如下: 复制代码 代码如下: function onNewClick() {     var url = "VesselScheduleNEW.aspx";     if (null!=newWin && newWin.closed) newWin=null;        if (null==newWin)  

  • JS基于MSClass和setInterval实现ajax定时采集信息并滚动显示的方法

    本文实例讲述了JS基于MSClass和setInterval实现ajax定时采集信息并滚动显示的方法.分享给大家供大家参考,具体如下: setTimeout 用于延时器,只执行一次. setInterval:用于多次执行. 项目中引用到jquery.timers-1.2.js定时器,并且MSClass做信息定期滚动,每3分钟执行一次,执行三次左右,滚动的次数越来越快,原因在于timers和MSClass都用了setInterval, 都会再次添加一个setInterval,最后导致几个setIn

  • Android互联网访问图片并在客户端显示的方法

    本文实例讲述了Android互联网访问图片并在客户端显示的方法.分享给大家供大家参考,具体如下: 1.布局界面 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:

  • js+html5获取用户地理位置信息并在Google地图上显示的方法

    本文实例讲述了js+html5获取用户地理位置信息并在Google地图上显示的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html> <html> <body> <p id="demo">Click the button to get your position:</p> <button onclick="getLocation()">Try It</button&

  • js控制输入框获得和失去焦点时状态显示的方法

    本文实例讲述了js控制输入框获得和失去焦点时状态显示的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"&

  • 完美解决thinkphp验证码出错无法显示的方法

    本文实例讲述了完美解决thinkphp验证码出错无法显示的方法.分享给大家供大家参考.具体分析如下: 今天做到验证码这一块,想到tp自带验证图片,大喜,但鼓捣半天不出来,一直是个小 X的样子. 官方提示如下: 如果无法显示验证码,请检查: ① PHP是否已经安装GD库支持: ② 输出之前是否有任何的输出(尤其是UTF8的BOM头信息输出): ③ Image类库是否正确导入: ④ 如果是中文验证码检查是否有拷贝字体文件到类库所在目录: 但是测试半天,不行!网上找来一个能用的方法,放到一个文件里执行

随机推荐