OpenLayer学习之聚合标注和信息框弹出

xiaoxiao2021-02-28  6

首先感觉我做的这个Demo是真的烂,查资料都没有多少,自己摸索着做出来,虽然比较烂,但是毕竟是一种思路

一、聚合图层的组成

1、Vector的source,这里面主要放feature,这个source不是直接加载到Vector图层中的source

for (var i = 0; i < dataSource.length; i++) { var coordinate = ol.proj.transform([dataSource[i].x, dataSource[i].y], 'EPSG:4326', 'EPSG:3857'); var attr = { attribute: dataSource[i].attribute }; features[i] = new ol.Feature({ geometry: new ol.geom.Point(coordinate), attribute: attr }); } console.log(features); var source = new ol.source.Vector({ features: features, });

2、声明ol.source.Cluster

var clusterSource = new ol.source.Cluster({ distance: 40, source: source });注意这里source是上面ol.source.Vector

二、初始化聚合图层

//加载聚合标注的矢量图层 var styleCache = {}; var layerVetor = new ol.layer.Vector({ source: clusterSource,//注意一定不要搞错了 style: function (feature, resolution) { var size = feature.get('features').length; var style = styleCache[size]; if (!style) { style = [new ol.style.Style({ image: new ol.style.Icon(/** @type {olx.style.IconOptions} */({ anchor: [0.5, 60], anchorOrigin: 'top-right', anchorXUnits: 'fraction', anchorYUnits: 'pixels', offsetOrigin: 'top-right', offset: [0, 1],//偏移量设置 scale: 0.2, //图标缩放比例 opacity: 0.75, //透明度 src: 'Script/Marker.png'//图标的url })), text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: 'blue' }) }) })]; styleCache[size] = style; } return style; } }); var map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.transform([104.06, 30.67], 'EPSG:4326', 'EPSG:3857'), zoom: 10 }), target: 'map', controls: ol.control.defaults().extend([ new ol.control.FullScreen(), new ol.control.OverviewMap(), new ol.control.Zoom(), new ol.control.MousePosition() ]), }); map.addLayer(layerVetor);

三、弹出框的设置

/** * 实现popup的html元素 */ var container = document.getElementById('popup'); var content = document.getElementById('popup-content'); var closer = document.getElementById('popup-closer'); /** * 在地图容器中创建一个Overlay */ var popup = new ol.Overlay(/** @type {olx.OverlayOptions} */({ element: container, autoPan: true, positioning: 'bottom-center', stopEvent: false, autoPanAnimation: { duration: 250 } })); map.addOverlay(popup); /** * 添加关闭按钮的单击事件(隐藏popup) * @return {boolean} Don't follow the href. */ closer.onclick = function () { popup.setPosition(undefined); //未定义popup位置 closer.blur(); //失去焦点 return false; }; /** * 动态创建popup的具体内容 * @param {string} title */ function addFeatrueInfo(info) { //新增a元素 var elementA = document.createElement('a'); content.appendChild(elementA); // 新建的div元素添加a子节点 var elementDiv1 = document.createElement('div'); elementDiv1.className = "markerText"; //elementDiv.innerText = info.att.text; setInnerText(elementDiv1, "所属省份:"+info.proname); content.appendChild(elementDiv1); // 为content添加div子节点 //新增div元素 var elementDiv = document.createElement('div'); elementDiv.className = "markerText"; //elementDiv.innerText = info.att.text; setInnerText(elementDiv,"地名:"+ info.name); content.appendChild(elementDiv); // 为content添加div子节点 } /** * 动态设置元素文本内容(兼容) */ function setInnerText(element, text) { if (typeof element.textContent == "string") { element.textContent = text; } else { element.innerText = text; } } layerVetor.on('click', function (evt) { var geometry = evt.Feature; console.log(geometry); }); /** * 为map添加点击事件监听,渲染弹出popup */ map.on('click', function (evt) { var coordinate = evt.coordinate; //判断当前单击处是否有要素,捕获到要素时弹出popup var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layerVetor) { return feature; }); var featuerInfo = feature.getProperties().features[0].N.attribute.attribute; if (feature) { content.innerHTML = ''; //清空popup的内容容器 addFeatrueInfo(featuerInfo); //在popup中加载当前要素的具体信息 if (popup.getPosition() == undefined) { popup.setPosition(coordinate); //设置popup的位置 } } }); /** * 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态 */ map.on('pointermove', function (e) { var pixel = map.getEventPixel(e.originalEvent); var hit = map.hasFeatureAtPixel(pixel); map.getTargetElement().style.cursor = hit ? 'pointer' : ''; })

四、全部源码

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>聚合和弹出</title> <link href="Script/ol.css" rel="stylesheet" /> <style type="text/css"> .ol-popup { position: absolute; background-color: white; -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2)); filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2)); padding: 15px; border-radius: 10px; border: 1px solid #cccccc; bottom: 12px; left: -50px; } .ol-popup:after, .ol-popup:before { top: 100%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; } .ol-popup:after { border-top-color: white; border-width: 10px; left: 48px; margin-left: -10px; } .ol-popup:before { border-top-color: #cccccc; border-width: 11px; left: 48px; margin-left: -11px; } .ol-popup-closer { text-decoration: none; position: absolute; top: 2px; right: 8px; } .ol-popup-closer:after { content: "✖"; height:30px; padding:12px; } #popup-content { font-size: 14px; font-family: "微软雅黑"; width:100px; } #popup-content .markerInfo { font-weight: bold; } </style> <script src="Script/ol.js"></script> <script src="Script/data.js"></script> </head> <body> <div id="map"> <!-- Popup --> <div id="popup" class="ol-popup"> <a href="#" id="popup-closer" class="ol-popup-closer"></a> <div id="popup-content"> </div> </div> </div> <script> var dataSource = county.items; var features = new Array(dataSource.length); for (var i = 0; i < dataSource.length; i++) { var coordinate = ol.proj.transform([dataSource[i].x, dataSource[i].y], 'EPSG:4326', 'EPSG:3857'); var attr = { attribute: dataSource[i].attribute }; features[i] = new ol.Feature({ geometry: new ol.geom.Point(coordinate), attribute: attr }); } console.log(features); var source = new ol.source.Vector({ features: features, }); var clusterSource = new ol.source.Cluster({ distance: 40, source: source }); //加载聚合标注的矢量图层 var styleCache = {}; var layerVetor = new ol.layer.Vector({ source: clusterSource, style: function (feature, resolution) { var size = feature.get('features').length; var style = styleCache[size]; if (!style) { style = [new ol.style.Style({ image: new ol.style.Icon(/** @type {olx.style.IconOptions} */({ anchor: [0.5, 60], anchorOrigin: 'top-right', anchorXUnits: 'fraction', anchorYUnits: 'pixels', offsetOrigin: 'top-right', offset: [0, 1],//偏移量设置 scale: 0.2, //图标缩放比例 opacity: 0.75, //透明度 src: 'Script/Marker.png'//图标的url })), text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: 'blue' }) }) })]; styleCache[size] = style; } return style; } }); var map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.transform([104.06, 30.67], 'EPSG:4326', 'EPSG:3857'), zoom: 10 }), target: 'map', controls: ol.control.defaults().extend([ new ol.control.FullScreen(), new ol.control.OverviewMap(), new ol.control.Zoom(), new ol.control.MousePosition() ]), }); map.addLayer(layerVetor); /** * 实现popup的html元素 */ var container = document.getElementById('popup'); var content = document.getElementById('popup-content'); var closer = document.getElementById('popup-closer'); /** * 在地图容器中创建一个Overlay */ var popup = new ol.Overlay(/** @type {olx.OverlayOptions} */({ element: container, autoPan: true, positioning: 'bottom-center', stopEvent: false, autoPanAnimation: { duration: 250 } })); map.addOverlay(popup); /** * 添加关闭按钮的单击事件(隐藏popup) * @return {boolean} Don't follow the href. */ closer.onclick = function () { popup.setPosition(undefined); //未定义popup位置 closer.blur(); //失去焦点 return false; }; /** * 动态创建popup的具体内容 * @param {string} title */ function addFeatrueInfo(info) { //新增a元素 var elementA = document.createElement('a'); content.appendChild(elementA); // 新建的div元素添加a子节点 var elementDiv1 = document.createElement('div'); elementDiv1.className = "markerText"; //elementDiv.innerText = info.att.text; setInnerText(elementDiv1, "所属省份:"+info.proname); content.appendChild(elementDiv1); // 为content添加div子节点 //新增div元素 var elementDiv = document.createElement('div'); elementDiv.className = "markerText"; //elementDiv.innerText = info.att.text; setInnerText(elementDiv,"地名:"+ info.name); content.appendChild(elementDiv); // 为content添加div子节点 } /** * 动态设置元素文本内容(兼容) */ function setInnerText(element, text) { if (typeof element.textContent == "string") { element.textContent = text; } else { element.innerText = text; } } layerVetor.on('click', function (evt) { var geometry = evt.Feature; console.log(geometry); }); /** * 为map添加点击事件监听,渲染弹出popup */ map.on('click', function (evt) { var coordinate = evt.coordinate; //判断当前单击处是否有要素,捕获到要素时弹出popup var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layerVetor) { return feature; }); var featuerInfo = feature.getProperties().features[0].N.attribute.attribute; if (feature) { content.innerHTML = ''; //清空popup的内容容器 addFeatrueInfo(featuerInfo); //在popup中加载当前要素的具体信息 if (popup.getPosition() == undefined) { popup.setPosition(coordinate); //设置popup的位置 } } }); /** * 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态 */ map.on('pointermove', function (e) { var pixel = map.getEventPixel(e.originalEvent); var hit = map.hasFeatureAtPixel(pixel); map.getTargetElement().style.cursor = hit ? 'pointer' : ''; }) </script> </body> </html>

五、效果图

六、总结

这里我用的是一个data数据,这里的坐标主要针对天地图比较准点,OSM好像看着不太准,就当看看效果图把,这里有Bug就是这个点击查询元素不太灵敏,我想应该有个缓冲区,但是始终没有找到,还有就是那个我把Attribute与放在要素里面,点击选择的时候这个获取atrrbute真困难,这个东西没少浪费时间

转载请注明原文地址: https://www.6miu.com/read-2149961.html

最新回复(0)