利用OpenLayers3在地图上显示标记并点击标记后显示弹出框

前言

在上一篇《利用全能电子地图下载器+GeoWebCache发布Arcgis Server缓存瓦片过程全记录》中,我们利用GeoWebCache作为瓦片地图服务器发布了瓦片地图。虽然在其中可以直接浏览,但是在GeoWebCache1.10.0中,官方内置的是OpenLayers2的版本,这个版本比较老旧,不能很好的适应诸如触屏设备等应用环境。所以,我想利用OpenLayers2的升级版OpenLayers3来进行地图显示,并增加显示地图标记点击标记后显示弹出框的功能,这两个也是比较常用的。
这篇文章可能会比较,我会对在标题中提到的总目标(在地图上显示标记并点击标记后显示弹出框)进行模块分解,并配上所用的API解析,化整为零嘛~各位也可以各取所需~
模块分解如下:
1、显示瓦片地图
2、在地图上显示标记
3、在点击标记后显示弹出框
Let’s Start~

环境

Part I 显示瓦片地图

效果

思路

GeoWebCache本身就是一个WMS服务,所以只需要利用OpenLayers3与这个WMS服务对接即可。

实现步骤

Step1:建立HTML文件,并引入OpenLayers的相关js与css文件

<link rel="stylesheet" type="text/css" href="../ol.css" />
<script src="../ol.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>

Step2:建立一个div,只需要一个ID属性

<div id="map"></div>

需要记住这个id值,后面的脚本会用到

Step3:获取投影坐标系,建立map对象

   //获取投影坐标系
   var pos = ol.proj.get('EPSG:3857');
    var map = new ol.Map({
        //地图容器div的ID
        target: 'map',
        //地图容器中加载的图层
        layers: [],
        view: new ol.View({
            //设置地图投影坐标系
            projection: pos,
            //设置地图加载时的初始中心点
            center: [13276805.940731, 3008561.497087],
            //缩放级别
            zoom: 19
        }),
    });

相关API:
1、new ol.Map
2、new ol.View
关于View构造参数的说明:
1、center参数的获取方式:
  a、在GeoWebCache中进入地图浏览模式,利用浏览器的开发者工具(这里以Google Chrome为例)打开NetWork选项卡

  b、随机点击Type值为png的连接,在Preview选项卡中,要是有瓦片地图的状态,而不是网格的状态,并记下URL,后续步骤要使用
  这我们想要的效果:

  这不是我们想要的效果:

  c、找到URL中的BBOX参数
  BBOX=13280473.174523,3009173.884415,13281084.670715,3009785.380607
  d、将前两个值,这里是13280473.1745233009173.884415填入center属性即可。
2、zoom参数:为下载瓦片地图时选择的地图级别。
注意二者要对应起来,zoom信息可以在Header(如果是Chrome浏览器的调试窗口)中找到

Step4:建立瓦片地图层

 var mlayer = new ol.layer.Tile({
        source: new ol.source.TileWMS({
            url: 'http://XXX.xxx.com/geowebcache/service/wms',
            params: {
                'LAYERS': 'fzgl',
                'FORMAT': 'image/png',
                'SRS': 'EPSG:3857'
            },
            tileGrid: new ol.tilegrid.TileGrid({
                resolutions: [156543.0339, 78271.51696, 39135.75848, 19567.87924, 9783.939621, 4891.96981, 2445.984905, 1222.992453, 611.496226, 305.748113, 152.874057, 76.437028, 38.218514, 19.109257, 9.554629, 4.777314, 2.388657, 1.194329, 0.597164, 0.298582],
                origin: [-20037508.3427892, 20037508.3430388]
            })
        })
    })

相关API:
1、new ol.layer.Tile
2、new ol.source.TileWMS
3、new ol.tilegrid.TileGrid
关于Tile对象的构造参数的说明:
1、url参数:如果你的Web Server(eg.Tomcat)没有经过特殊配置的话,直接替换XXX.xxx.com为你的地址即可
2、params参数、FORMAT参数、SRS参数,都可以从Step3中记下的URL里的对应参数位置找到
3、resolutions 参数:可以从geowebcache对应的地图预览的网页源代码找到

4、origin 参数:可以从Arcgis瓦片的conf.xml中找到

4、这几个参数是最基本的,如果有缺失或填写错误,地图将无法正常渲染

Step5:将创建好的瓦片地图层添加进Map中

map.addLayer(mlayer)

相关API
1、map.addLayer

Done!
实例演示,点这里

Part II 在地图上显示标记

效果

这里写图片描述

思路

在地图上显示标记,相当于在原来的瓦片地图层上由新叠加了一层,在OpenLayers中称为矢量层。可以把这种叠加的原理理解为PS中的图层,通过各种图层的叠加,达到我们想要的效果。这些地图上的图标,就存在与矢量层上。所以,我们只需要创建矢量层,并添加进map中即可。

实现步骤

Step1:创建空的矢量容器

注:在OpenLayers中,每一个地图上的图标,称做一个Feature,这个矢量容器就是用来装Feature的

var vectorSource = new ol.source.Vector({});

相关API:
1、new ol.source.Vector

Step2:创建Feature,并添加进矢量容器中

        //创建图标特性
        var iconFeature = new ol.Feature({
            geometry: new ol.geom.Point([t1, t2], "XY"),
            name: "my Icon",
        });
        //将图标特性添加进矢量中
        vectorSource.addFeature(iconFeature);

相关API:
1、new ol.Feature
2、new ol.geom.Point
3、vectorSource.addFeature
几点说明:
1、上面代码中的t1、t2即要显示标记的位置,填入你想让标记出现的经纬度即可。

Step3:创建标记的样式

  //创建图标样式
    var iconStyle = new ol.style.Style({
        image: new ol.style.Icon({
            opacity: 0.75,
            src: "http://openlayers.org/en/v3.9.0/examples/data/icon.png"
        }),
    });

相关API:
1、new ol.style.Style
2、new ol.style.Icon

Step4:创建矢量层,并添加进map层

   //创建矢量层
    var vectorLayer = new ol.layer.Vector({
        source: vectorSource,
        style: iconStyle
    });
    //添加进map层
    map.addLayer(vectorLayer);

相关API:
1、new ol.layer.Vector

Done!
示例演示,点这里

Part III 在点击标记后显示弹出框

效果

思路

这个是在这几个案例中最复杂的一个了。
分析:在OpenLayers3中,弹出框是一个Overlay,overlay的中文是覆盖物的意思,弹出框不就是一个覆盖物吗?
这里又牵扯到一个新的知识点,那就是地图的事件监听,在map类中有一个on方法,但这个方法的确能对点击事件进行监听,但是是对整个map的。也就是说,我点击地图上的任何位置,都会触发这个监听事件,效果上并不是我们想要的。我们想要的是在点击标记后才触发监听事件。幸运的是,OpenLayers在map类中为我们提供了一个函数,叫forEachFeatureAtPixe,这个函数的工作原理有点类似物理中的光电门,这个函数会对所给定的像素范围进行扫描,如果发现Feature(标记就是一个Feature),就会触发回掉函数。那么如何给定点击像素呢?OpenLayers又很贴心地给我们准备了getEventPixe函数,这个函数会在事件触发时,返回对应的像素范围。
总结思路: 在点击地图时触发getEventPixel函数返回区域->调用forEachFeatureAtPixel进行像素区域扫描,如果发现Feature,则激活弹出框。

实现步骤

Step1:在HTML中添加一个div,用于显示弹出框

<div id="popup" class="ol-popup">
        <a href="#" id="popup-closer" class="ol-popup-closer"></a>
        <div id="popup-content"></div>
</div>

1、这里所有的id都需要记录
2、这里还需要对弹出框设定样式,例子CSS样式将在文章最后的源码中给出

Step2:在js中获取HTML元素

var container = document.getElementById("popup");
var content = document.getElementById("popup-content");
var popupCloser = document.getElementById("popup-closer");

1、container:最外层包含所有元素的div
2、content:显示弹出框具体内容的div
3、popupCloser:弹出框的关闭按钮,是一个a标签

Step3:创建一个Overlay

 var overlay = new ol.Overlay({
         //设置弹出框的容器
        element: container,
        //是否自动平移,即假如标记在屏幕边缘,弹出时自动平移地图使弹出框完全可见
        autoPan: true
    });

相关API:
1、new ol.Overlay

Step4:在map上绑定点击事件监听

map.on('click',function(e){
        //在点击时获取像素区域
        var pixel = map.getEventPixel(e.originalEvent);
        map.forEachFeatureAtPixel(pixel,function(feature){
            //coodinate存放了点击时的坐标信息
            var coodinate = e.coordinate;
            //设置弹出框内容,可以HTML自定义
            content.innerHTML = "<p>你点击的坐标为:" + coodinate + "</p>";
            //设置overlay的显示位置
            overlay.setPosition(coodinate);
            //显示overlay
            map.addOverlay(overlay);
        });
    });

相关API:
1、map.on
2、map.getEventPixel
3、map.forEachFeatureAtPixel
4、overlay.setPosition
5、map.addOverlay

Done! 至此,在地图上点击标记时,就会有弹出框显示了~
示例演示,点这里

演示与示例代码合集

GitHub
演示合集

本文用到的API合集

Openlayer3.13.1的几个API的部分翻译

参考资料

1、Openlayers3 加载Geowebcache 发布的 ArcGIS 切片地图
2、Openlayer 3 的点击弹出框

写在最后

由于OpenLayers3几乎没有中文的API,于是乎就去翻译了,翻译了两天,部分语句采用了Google Translate的翻译结果。如果出现错误可以在评论区反馈~多谢谅解~~其实翻译一遍在结合代码理解会更清晰一些~

以下是基于 Vue2 和 OpenLayers 的添加标注、聚合点和点击标注信息弹窗的代码示例: ```html <template> <div id="map"></div> </template> <script> import &#39;ol/ol.css&#39;; import olMap from &#39;ol/Map&#39;; import olView from &#39;ol/View&#39;; import olFeature from &#39;ol/Feature&#39;; import olPoint from &#39;ol/geom/Point&#39;; import olLayerVector from &#39;ol/layer/Vector&#39;; import olSourceVector from &#39;ol/source/Vector&#39;; import olStyle from &#39;ol/style/Style&#39;; import olIcon from &#39;ol/style/Icon&#39;; import olCluster from &#39;ol/source/Cluster&#39;; import { fromLonLat } from &#39;ol/proj&#39;; export default { data() { return { map: null, vectorLayer: null, clusterLayer: null, markers: [ { id: 1, name: &#39;Marker 1&#39;, lat: 39.536, lon: 116.681 }, { id: 2, name: &#39;Marker 2&#39;, lat: 39.543, lon: 116.676 }, { id: 3, name: &#39;Marker 3&#39;, lat: 39.547, lon: 116.684 }, { id: 4, name: &#39;Marker 4&#39;, lat: 39.554, lon: 116.682 }, { id: 5, name: &#39;Marker 5&#39;, lat: 39.552, lon: 116.69 }, { id: 6, name: &#39;Marker 6&#39;, lat: 39.546, lon: 116.694 }, ], }; }, mounted() { this.initMap(); this.addMarkers(); }, methods: { initMap() { this.map = new olMap({ target: &#39;map&#39;, view: new olView({ center: fromLonLat([116.681, 39.536]), zoom: 13, }), }); }, addMarkers() { const features = []; this.markers.forEach((marker) => { const feature = new olFeature({ geometry: new olPoint(fromLonLat([marker.lon, marker.lat])), name: marker.name, }); feature.setId(marker.id); feature.setStyle(this.createMarkerStyle()); features.push(feature); }); const vectorSource = new olSourceVector({ features, }); this.vectorLayer = new olLayerVector({ source: vectorSource, }); this.clusterLayer = new olLayerVector({ source: new olCluster({ distance: 40, source: vectorSource, }), style: this.createClusterStyle(), }); this.map.addLayer(this.clusterLayer); this.map.addLayer(this.vectorLayer); this.map.on(&#39;click&#39;, (event) => { this.showMarkerInfo(event.coordinate); }); }, createMarkerStyle() { return new olStyle({ image: new olIcon({ src: &#39;https://openlayers.org/en/latest/examples/data/icon.png&#39;, scale: 0.5, }), }); }, createClusterStyle() { return new olStyle({ image: new olIcon({ src: &#39;https://openlayers.org/en/latest/examples/data/icon.png&#39;, scale: 0.5, }), text: new olStyle.Text({ text: &#39;{count}&#39;, font: &#39;bold 14px sans-serif&#39;, fill: new olStyle.Fill({ color: &#39;#fff&#39;, }), }), }); }, showMarkerInfo(coordinate) { const feature = this.map.getClosestFeatureToCoordinate(coordinate); if (feature) { const id = feature.getId(); const name = feature.get(&#39;name&#39;); alert(`ID: ${id}\nName: ${name}`); } }, }, }; </script> <style> #map { width: 100%; height: 500px; } </style> ``` 代码说明: 1. 在 `data` 中定义了地图对象和标注数据。 2. 在 `mounted` 钩子中调用 `initMap` 方法初始化地图,调用 `addMarkers` 方法添加标注和聚合点,绑定地图的 `click` 事件。 3. `initMap` 方法创建地图对象,设置中心点和缩放等级。 4. `addMarkers` 方法循环标注数据,创建标注的 `Feature`,设置标注的样式和 ID,将所有标注 `Feature` 添加到矢量数据源中,创建标注图层和聚合图层,将聚合图层和标注图层添加到地图中。 5. `createMarkerStyle` 方法创建标注样式,使用 `olIcon` 设置标注图标的图片地址和缩放比例。 6. `createClusterStyle` 方法创建聚合点样式,使用 `olIcon` 设置聚合点图标的图片地址和缩放比例,使用 `olStyle.Text` 设置聚合点文本的样式和内容,使用 `{count}` 表示聚合点内标注的数量。 7. `showMarkerInfo` 方法根据点击的坐标获取最近的标注,获取标注的 ID 和名称,弹出信息框显示。 注意:以上示例代码仅为参考,具体实现需要根据实际情况进行调整。
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值