Openlayers 自定义气泡框以及定位到气泡框

  • OpenLayers 教程
    • Openlayers 自定义气泡框以及定位到气泡框
    • 在线示例

OpenLayers 教程

Openlayers 气泡框功能,主要用来展示地图要素的属性信息,也被称为气泡、卡片、弹出框等等,笔者习惯称为气泡框。

气泡框功能很常用,场景一般是,在地图叠加点线面的时候同时展示当前要素(Feature)的基础信息,比如名称、数量、地址等;还有就是点击地图叠加元素的时候再弹出气泡框,来展示信息。

气泡框因容器大小限制,一般只展示简略信息,想展示详细信息的话,往往通过新开页面或者弹出大的 div 容器展示。

一般来说,气泡框属于地图覆盖物(Overlay),属于 dom 元素,没有在 canvas 内部,层级位于图层之上,作为顶层元素存在;气泡框一般都会包含关闭图标或按钮,可以点击关闭,也有特殊场景,不允许关闭,不过如果不关闭的话,直接使用 dom 元素实现就可以。

气泡框作为地图对象元素加载的好处之一,就是可以跟随地图移动,效果更加符合使用习惯。

本文主要介绍,气泡框的初始化、气泡框展示信息、气泡框样式、气泡框定位

Openlayers 自定义气泡框以及定位到气泡框

<html lang="en">
<head><meta charSet="utf-8"><!--注意:openlayers 原版的比较慢,这里引起自己服务器版--><link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css"><style>/* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */.map {height: 700px;width: 100%;float: left;}/*气泡框容器样式*/.leaflet-container {position: absolute;-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);-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));bottom: -12px;}/*气泡框关闭按钮样式*/.leaflet-container a.leaflet-popup-close-button {position: absolute;top: 0;right: 0;padding: 4px 4px 0 0;width: 18px;height: 14px;background: 0;color: #ffffff;text-align: center;text-decoration: none;font: 1pc/14px Tahoma, Verdana, sans-serif;font-weight: 700}/*气泡框内容样式*/.common-popup .leaflet-popup-content-wrapper {background: transparent;box-shadow: none;padding: 0;border-radius: 0;}/*气泡框下角*/.common-popup .leaflet-popup-tip {margin-left: 120px}.leaflet-popup-tip-container {position: relative;overflow: hidden;margin: 0;height: 28px}.leaflet-popup-tip {margin: -10px auto 0;padding: 1px;width: 17px;height: 18px;-webkit-transform: rotate(45deg);transform: rotate(45deg);-ms-transform: rotate(45deg)}.leaflet-popup-content-wrapper, .leaflet-popup-tip {background: #fff;box-shadow: 0 3px 14px rgba(0, 0, 0, .4)}/*自定义气泡框样式*/.customer-popup-southejor-style {border: 1px solid #fff;border-radius: 5px;background: #1a90c587;color: #fff;box-shadow: inset 0 0 4px 2px #fff;}/*自定义气泡框标题样式*/.customer-popup-southejor-title {height: 10%;background-color: #03a9f48f;padding: 2px;font-size: 20px;text-align: center;}</style><!--注意:openlayers 原版的比较慢,这里引起自己服务器版--><script src="http://openlayers.vip/examples/resources/ol.js"></script><script src="http://openlayers.vip/examples/resources/jquery-3.5.1.min.js"></script><script src="./tiandituLayers.js"></script><title>OpenLayers example</title>
</head>
<body>
<h2>OpenLayers Popup</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div><script type="text/javascript">var map = new ol.Map({// 地图容器target: 'map',// 地图图层,比如底图、矢量图等layers: [getIMG_CLayer(),getIBO_CLayer(),getCIA_CLayer(),],// 地图视野view: new ol.View({projection: "EPSG:4326",// 定位center: [115.67724700667199, 37.73879478106912],// 缩放zoom: 6,maxZoom: 18,minZoom: 1,})});// 开启图形要素点击事件map.on('click', function (event) {this.forEachFeatureAtPixel(event.pixel, function (feature) {// 为点击的feature发送自定义的click消息feature.dispatchEvent && feature.dispatchEvent({type: 'click', event: event});});});// 初始化气泡框createPopup();// 默认样式var defaultStyle = new ol.style.Style({//边框样式stroke: new ol.style.Stroke({color: 'white',width: 2,}),//填充样式fill: new ol.style.Fill({color: 'rgba(255, 255, 255, 0.7)',}),// 点样式image: new ol.style.Icon({// 允许跨域,如果不设置,打印地图不会打印crossOrigin: 'anonymous',// 标注图片和文字之间的距离anchor: [0.5, 0],// 图片的偏移offset: [0, 0],// 图片的锚点,一般来说,都是右下角anchorOrigin: 'bottom-right',//图标的urlsrc: "http://api.tianditu.gov.cn/v4.0/image/marker-icon.png",scale: 1,})})// 初始化图层var layer = initVectorLayer();// 面和点var feature = undefined, featurePoint = undefined;addFeatures();// 添加点线面function addFeatures() {featurePoint = getFeatureByWKT("POINT(116.17983834030585 39.98298600752048)");feature = getFeatureByWKT("POLYGON((115.13540462521966 37.877850766866445,116.31094173459466 39.042401548116445,117.23379329709466 38.130536313741445,117.10195735959466 37.295575376241445,115.64077571896966 36.976971860616445,115.26724056271966 37.174725766866445,115.13540462521966 37.877850766866445))");//设置显示属性feature.set('content:内容', '这是一个面状图形要素');feature.set('other:其他属性', '还有其他面状属性');featurePoint.set('content:内容', '这是一个点图形要素');featurePoint.set('other:其他属性', '还有其他点属性');//定义绑定事件let clickFunc = function (e) {// 获取要展示的属性信息let popupStr = getPopupHtml(e.target);//获取地图对象let temp = '<div class="customer-popup-southejor-style">' +'                <div class="customer-popup-southejor-title">\n' +'                  <span>气泡框</span>\n' +'                </div>\n' +'                <div style="font-size: 16px; padding: 5px;">' +'                   <div class="customer-popup-southejor-index" style="padding-left: 10px;">' +popupStr.content +'                   </div>' +'                </div>\n' +'              </div>'//打开气泡框openInfoWindowHtml(e.target, temp)}//绑定事件feature.on('click', clickFunc);featurePoint.on('click', clickFunc);layer.getSource().addFeatures([feature, featurePoint]);}/*** @todo 矢量图层* @returns {VectorLayer}* @constructor*/function initVectorLayer() {//实例化一个矢量图层Vector作为绘制层let source = new ol.source.Vector();//创建一个图层let customVectorLayer = new ol.layer.Vector({source: source,zIndex: 2,//设置样式style: defaultStyle,});//将绘制层添加到地图容器中map.addLayer(customVectorLayer);return customVectorLayer;}/*** @todo wkt格式数据转化成图形对象* @param {string} wkt   "POINT(112.7197265625,39.18164062499999)" 格式数据* @param {string|Projection} sourceCode 源投影坐标系* @param {string|Projection} targetCode 目标投影坐标系* @returns {Feature}*/function getFeatureByWKT(wkt, sourceCode, targetCode) {try {let view = map.getView();if (!wkt) {return null;}let format = new ol.format.WKT();let feature;feature = format.readFeature(wkt, {featureProjection: targetCode || view.getProjection(),dataProjection: sourceCode || view.getProjection(),});return feature;} catch (e) {console.log(e);return null;}}/*** todo 创建 popup 气泡框元素* @param*/function createPopup() {// 气泡框容器字符串var popupStr = "<div id='popup-leaflet-container-southejor' class=\"leaflet-container\" > \n" +"      <div class=\"leaflet-popup-pane\">\n" +"       <div class=\"leaflet-popup common-popup\">\n" +"        <a id='popup-closer' class=\"leaflet-popup-close-button\" href=\"JavaScript:void(0)\">&times;</a>\n" +"        <div class=\"leaflet-popup-content-wrapper\">\n" +"        </div>\n" +"        <div class=\"leaflet-popup-tip-container\">\n" +"         <div class=\"leaflet-popup-tip\"></div>\n" +"        </div>\n" +"       </div>\n" +"      </div>\n" +"     </div>";// 创建气泡框容器let popupDiv = document.createElement("div"); //创建一个div标签// 设置 idpopupDiv.id = "mapPopup";// 初始化不显示popupDiv.style.display = 'none';// 初始化容器popupDiv.innerHTML = popupStr;//限制页面只能出现一个气泡框if (document.getElementsByTagName('body')[0].contains(popupDiv)) {document.getElementsByTagName('body')[0].removeChild(popupDiv);}document.getElementsByTagName('body')[0].appendChild(popupDiv);return initPopup(popupDiv);}// 气泡框,主体,关闭按钮var popup, contentBody, closerPopup;/*** todo 初始化气泡框* @returns {Overlay}*/function initPopup(popupContainer) {//气泡框-内容IDcontentBody = $('#popup-leaflet-container-southejor .leaflet-popup-content-wrapper')[0];//气泡框-关闭IDcloserPopup = document.getElementById('popup-closer');// 设置为显示popupContainer.style.display = 'block';//气泡框覆盖层popup = new ol.Overlay({// 容器element: popupContainer,// 当Popup超出地图边界时,为了Popup全部可见,自动移动到可视范围autoPan: true,autoPanAnimation: {//当Popup超出地图边界时,为了Popup全部可见,地图移动的速度.duration: 250}});return popup;}function openInfoWindowHtml(featureTemp, content) {try {// 如果没有图形要素参数,则打开默认气泡框if (!featureTemp) {contentBody.innerHTML.trim() ? map.addOverlay(popup) : alert('请先点击图形要素(面或点)!');return;}// 更新显示属性contentBody.innerHTML = content;// 获取图形要素中心点var center = ol.extent.getCenter(featureTemp.getGeometry().getExtent());// 气泡框设置中心点popup.setPosition(center);// 移除上一个气泡框map.removeOverlay(popup);// 获取图形要素类型let featureType = featureTemp.getGeometry().getType();//这 里面和线图形与点图形不一样;如果是点图层(图标),则气泡框上移// 气泡框的 setOffset 可以根据实际调整if (featureType == 'Point') {let styleTemp = featureTemp.getStyle() || layer.getStyle();if (styleTemp && styleTemp.getImage()) {let size = styleTemp.getImage().getSize();let scale = styleTemp.getImage().getScale();if (size && size.length > 1) {popup.setOffset([-10, -size[1] * scale]);} else {popup.setOffset([0, -40]);}} else {popup.setOffset([0, -5]);}//其他图形则正常} else {popup.setOffset([-10, 0]);}// 添加气泡框map.addOverlay(popup);// 绑定关闭按钮事件closerPopup.onclick = function () {map.removeOverlay(popup);};// 气泡框宽度let popupWidth = 300;// 调整位置let popupPointLeft = (popupWidth / 2);// 调整横向偏移$(map.getTargetElement()).find(".leaflet-container").width(popupWidth + "px");$(map.getTargetElement()).find(".leaflet-container").css('right', -popupPointLeft + "px");$(map.getTargetElement()).find(".leaflet-popup-tip-container .leaflet-popup-tip").css("margin-left", popupPointLeft + "px");return popup;} catch (e) {console.log(e)}}// 获取气泡框属性function getPopupHtml(feature) {if (!feature) {return;}let popup = {};// 定义 table 容器let content = "<table class='popup-table-html-show-southejor' style='width: 100%;color:white'>";// 获取图形要素所有属性let featureProperties = feature.getProperties();// 设置字段和属性宽度let tdColumn = '35%', tdField = '65%';for (let featureElement in featureProperties) {// 这里需要跟前边 feature 属性定义对应;// 前边定义为:字段:值if (featureElement && featureElement.indexOf(":") != -1) {let featureElementArr = featureElement.split(":");content += "<tr style='height: 25px;'>";// 拼接属性信息content += "<td style='border-width: 0px 0px 1px 0px;word-wrap:break-word;" +"word-break:break-all;width: " + tdColumn + "'><div>" + featureElementArr[1] + " : </div></td>" +"<td style='border-width: 0px 0px 1px 0px;word-wrap:break-word;word-break:break-all;" +"width: " + tdField + "'><div class='popupIdentity-" + featureElementArr[0] + "'>" +featureProperties[featureElement] + "</div></td>";content += "</tr>";}}popup.content = content += "</table>";return popup;}/***  todo 定位到气泡框*/function moveToPopup() {// 用于定位的[x,y]let xy;// 图形要素的类型;面线和点获取 xy 方式不同let type = feature.getGeometry().getType();// 获取面线和点的 xyif ('Polygon' == type || 'LineString' == type) {xy = ol.extent.getCenter(feature.getGeometry().getExtent());} else {xy = feature.getGeometry().getCoordinates();}// 定位位置(y 轴)let init = 500;// 获取气泡框高度let heightTemp = init + $('#popup-leaflet-container-southejor').height() - 40;heightTemp = heightTemp || 680;// 计算 y 轴间隔let gap = map.getCoordinateFromPixel([300, heightTemp])[1] - map.getCoordinateFromPixel([300, init])[1];xy && xy.length > 1 && (xy[1] = xy[1] - gap);// 定位;位置,定位时长let flyTo = function (location, time) {let duration = time ? time : 2000;let zoom = map.getView().getZoom();let parts = 2;let called = false;// 定位回调function callback(complete) {--parts;if (called) {return;}if (parts === 0 || !complete) {called = true;}}// 定位动作map.getView().animate({center: location,duration: duration}, callback);// 定位动作map.getView().animate({zoom: zoom - 1,duration: duration / 2}, {zoom: zoom,duration: duration / 2}, callback);}flyTo(xy, 1000);}/***  todo 关闭气泡框* @param _map*/function closeInfoWindowHtml() {map.removeOverlay(popup);}
</script>
<button id="openInfoWindowHtml" onClick="openInfoWindowHtml()">打开气泡框</button>
<button id="moveToPopup" onClick="moveToPopup()">定位到气泡框</button>
<button id="closeInfoWindowHtml" onClick="closeInfoWindowHtml()">关闭气泡框</button>
</body>
</html>

在线示例

Openlayers 自定义气泡框:Openlayers feature popup

Openlayers 自定义气泡框以及定位到气泡框相关推荐

  1. java中如何定位文本框_div定位在文本框下

    模板名称: 计费方式: 数量金额 模板类型: 按区域计费全国统一计费 免邮条件: 买${chargeMode}(含)以上免邮, 至的运费: 买${chargeMode}(含)以内, 收邮费元, 每多买 ...

  2. ECharts 创建中国气泡地图和定位图表点 点击地区域高亮显示

    ECharts 创建中国气泡地图和定位图表点 点击地区域高亮显示 ECharts 官方案例: https://www.makeapie.com/editor.html?c=x_kEnG-Ggq 效果如 ...

  3. 微信气泡主题设置_微信气泡主题设置方法

    微信气泡怎么设置?微信出聊天气泡啦,今天给大家提供各个品牌手机的设置方法,这里的气泡各种风格都有,用户在线就可以直接下载,没有任何收费的功能,已经用户都下载了,还可以和闺蜜男朋友使用同款气泡哦,喜欢的 ...

  4. webdriver--单选、复选及下拉框的定位

    单选radiobutton的操作 两种情况,一种是各个button元素的属性都有唯一定位值,可以直接用属性唯一值定位:另一种就是一组各方面属性值都一样的radiobutton,除了text,可以用组元 ...

  5. 大型情感剧集Selenium:4_老中医教你(单/多/下拉框)选项定位 #华为云·寻找黑马程序员#

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  6. 播音气泡音是什么,气泡音怎么学,气泡音怎么练

    气泡音是什么,气泡音怎么学,气泡音怎么练?气泡音是一种高度声气协调状态下发出来的声音.通过气泡音可以体会声带完全闭合下丹田气息支撑发声的感觉. 对于气泡音,很多人都有一个误区:认为气泡音是通过简单训练 ...

  7. 微信气泡主题设置_微信气泡主题怎么设置_微信气泡主题怎么设置方法_掌通手游...

    微信气泡主题怎么设置方法.微信是大家在生活中经常使用的一款软件,大家在这里,可以跟自己的好友一起互动交谈,说出各种想法内容.在游戏中,大家有的时候,也会想去设置各种东西内容,让自己的页面看上去更多高大 ...

  8. messagrbox自定义按钮c语言,基于dialogbox修改可自定义按钮及事件的弹出框插件

    插件描述:基于dialogbox1.0修改可自定义按钮及事件的弹出框插件,每个按钮可绑定单独的触发事件,并且能支持将弹出框作为一个表单来填入数据并获取 $('body').dialogbox({ ty ...

  9. selenium 下拉框失焦定位

    Selenium 中文名为自动化测试工具,它可以用于自动化 Web 浏览器的操作,以帮助测试网站的功能.如果要在 Selenium 中定位下拉框,你可以使用定位方法 find_element_by_i ...

  10. Easyexcel生成excel并通过自定义注解实现下拉框以及动态下拉框(将数据库中的数据显示在excel下拉框中)

    首先需要定义excel实体类 @Data @ColumnWidth(22) @HeadRowHeight(30) public class ExcelProductDTO {//动态下拉框,可以查询数 ...

最新文章

  1. PMON failed to acquire latch, see PMON dump
  2. NetDevOps — NETCONF 协议
  3. MacDown的使用规范总结 96 卞泽 2016.04.08 15:05* 字数 1273 阅读 4295评论 10喜欢 34 MacDown是什么? 请点击here MacDown下载地址,请点
  4. 矢量合成和分解的法则_力的合成与分解专题解析,寒假复习!
  5. 如何实现动态水球图 --》 echars结合echarts-liquidfill实现
  6. CSMA/CD协议(一目了然,看过都说好)
  7. iOS开发 - 不进入待机(屏幕保持唤醒)---UIApplication学习
  8. bilibili源码_bilibili源码泄漏后,程序员们从代码里扒出来的彩蛋
  9. 实际参数列表和形式参数列表长度不同_Dynamo参数化轴网,这些对你很有帮助
  10. attributeerror: __exit___利用__attribute__特性提高 APP 的鲁棒性
  11. 京东方10.1寸1280*800薄屏EV101WXM-N10-BOE工业屏
  12. 感觉丧的时候,读一读曾国藩
  13. android云测如何使用教程,iTestin使用教程-Testin云测.PDF
  14. PADS学习之路09-PADS LOGIC创建原理图工程文件
  15. zbb20180921 spring事物的七种事物传播属性行为及五种隔离级别
  16. html5 霸刀,基于Html5技术研发3D页游《霸刀》3月28日首测
  17. Ubuntu安装Microsoft office
  18. mock.js 使用说明( 简单而有效 )
  19. 小程序富文本图片放大功能
  20. 阿里巴巴ICBU技术部22届实习招聘

热门文章

  1. tensorflow配置默认工作路径
  2. 美团和饿了么分别有什么优势和劣势?
  3. 我的第一届acm大赛
  4. 【Java】Java学习笔记(5)——Java泛型作业函数题
  5. [转帖]张汝京:告别中芯国际这10年
  6. poj:2455 Secret Milking Machine 秘密挤奶机(二分+最大流)
  7. Windows:在Windows下创建并删除软连接
  8. DS18B20温度传感器(STM32F103C8T6)
  9. PDM中BOM管理技术的研究及其应用
  10. C# 通过Http获取网页内容