OpenLayers 3 之 弹出框(popup)

28 篇文章 38 订阅
26 篇文章 192 订阅

摘要

         上回说到,加载完地图后,我们想更多一点交互,而不仅仅是缩放和平移,赋予地图多一点的生命 ~-~!点击地图,它至少应该知道我是在哪里点击了,并且弹出一个气球类似的框框告诉我!这次,我们就来尝试给我们的地图加上这个能力!

         PS:这次的例子是基于上一篇的加载地图的代码的哦!在上一篇的基础上增删修改,所以读读前一篇是很有必要的哦!

正文

        在OpenLayers2.x的那个年代 ~-~|,我们知道OpenLayers有一个类(Popup)是专门负责这项“弹出气球”功能的。现在,到了3.x的时代,不同于OpenLayers 2.x,OpenLayers 3.x去除了Popup类,新增加了Overlay类,用于实现与Popup相同的弹出效果。在OpenLayers3.x的Overlay类定义中(定义这里找),Overlay的初始化属性如下:

/**
* @enum {string}
*/
ol.OverlayProperty = {
  ELEMENT: 'element',
  MAP: 'map',
  OFFSET: 'offset',
  POSITION: 'position',
  POSITIONING: 'positioning'
};

其中,ELEMENT代表要转换成overlay的HTML元素,可能是一个DIV标签,MAP是要绑定的地图对象,POSITION是点击时Popup放置的位置。

所以说为了产生弹出框的效果,那么HTML文件中要有相应的元素,那么我们就定义一些元素:

<div id="popup" class="ol-popup">
    <a href="#" id="popup-closer" class="ol-popup-closer"></a>
    <div id="popup-content" style="width:300px; height:120px;"></div>
</div>

这些元素的CSS样式类,在下面的代码中,会贴出来,主要就是一些对popup的美化作用,可以不用太在意哈。

然后取得该元素container,并将获得的元素传入overlay对象:

var container = document.getElementById('popup');
var overlay = new ol.Overlay(/** @type {olx.OverlayOptions} */ ({
  element: container,
  autoPan: true,
  autoPanAnimation: {
    duration: 250   //当Popup超出地图边界时,为了Popup全部可见,地图移动的速度. 
  }
}));

这样,弹出的框框我们就准备好了。下一步需要为Map绑定点击事件,这样,当我们点击地图上的相应位置时,才会触发弹出框框嘛!

/**
 * Add a click handler to the map to render the popup.
 */
map.addEventListener('click', function(evt) {
  var coordinate = evt.coordinate;
  var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(
      coordinate, 'EPSG:3857', 'EPSG:4326'));
  content.innerHTML = '<p>你点击的坐标是:</p><code>' + hdms + '</code>';
  overlay.setPosition(coordinate);
  map.addOverlay(overlay);
});

这里为了最大程度兼容各个浏览器,我们使用了DOM0级绑定事件的方式,event对象(evt)保存着点击的点坐标,在相应的位置显示框框即可(overlay.setPosition()),最后,将popup加到地图上。

OK!至此,我们可以测试一下了: DUANG! 是不是有“加特效”的感觉?~-~|


最后,附上完整代码

HTML文件

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="http://openlayers.org/en/v3.3.0/css/ol.css" type="text/css">
    <style>
      .map {
        height: 400px;
        width: 100%;
      }
      .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: "✖";
      }
    </style>
    <title>OpenLayers 3 example</title>
  </head>
  <body>
    <h2>My Map</h2>
    <div id="map" class="map">
        <div id="popup" class="ol-popup">
            <a href="#" id="popup-closer" class="ol-popup-closer"></a>
            <div id="popup-content" style="width:300px; height:120px;"></div>
        </div>
    </div>
    <script src="http://openlayers.org/en/v3.3.0/build/ol.js" type="text/javascript"></script>
    <script type="text/javascript">
      map = new ol.Map({
        target: 'map',
        layers: [
          new ol.layer.Tile({
            source: new ol.source.MapQuest({layer: 'sat'})
          })
        ],
        view: new ol.View({
          center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'),
          zoom: 4
        })
      });
    </script>
    <script src="popup.js" type="text/javascript"></script>
  </body>
</html>


 
JS文件(popup.js) 

/**
 * Elements that make up the popup.
 */
var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');


/**
 * Add a click handler to hide the popup.
 * @return {boolean} Don't follow the href.
 */
closer.onclick = function() {
  overlay.setPosition(undefined);
  closer.blur();
  return false;
};


/**
 * Create an overlay to anchor the popup to the map.
 */
var overlay = new ol.Overlay(/** @type {olx.OverlayOptions} */ ({
  element: container,
  autoPan: true,
  autoPanAnimation: {
    duration: 250   //当Popup超出地图边界时,为了Popup全部可见,地图移动的速度. 单位为毫秒(ms)
  }
}));


/**
 * Add a click handler to the map to render the popup.
 */
map.addEventListener('click', function(evt) {
  var coordinate = evt.coordinate;
  var hdms = ol.coordinate.toStringHDMS(ol.proj.transform(
      coordinate, 'EPSG:3857', 'EPSG:4326'));
  content.innerHTML = '<p>你点击的坐标是:</p><code>' + hdms + '</code>';
  overlay.setPosition(coordinate);
  map.addOverlay(overlay);
});

        其中HTML页中的那些CSS样式“.ol-popup:before”是啥意思呢?.ol-popup我们知道,这是定义一个CSS的样式类,在相应的元素中加上class=“ol-popup”就可以使用定义的样式,后面的“:before”表示在相应的元素前面插入相应的样式,“:after”与之同理,只不过是在元素后面插入相应的样式。没有看懂的可以在这里找到说明。

还有还有,为什么要把JS文件引用那几句放<body>元素的最后面呢?

<script src="http://openlayers.org/en/v3.3.0/build/ol.js" type="text/javascript"></script>
<script src="popup.js" type="text/javascript"></script>

        原因是这样的:在文档的<head>元素中包含JavaScript文件,意味着必须等到全部JavaScript都被下载、解析和执行完成以后,才能开始呈现页面的内容(浏览器遇到<body>标签,才开始呈现内容)。所以,对于需要很多JavaScript代码的页面来说,肯定会导致浏览器呈现页面时出现延迟,而延迟的时候,浏览器窗口将是一篇空白!

        当然,对于JavaScript文件需要比较少的页面可以写在<head>中,影响并不大。但毕竟,养成好习惯还是好的哦!~-~


总结

        这次我们能够知道我们点击的是哪里了!通过简单的坐标比较,我们就知道我们点击的是哪个省,哪个市了。。。

        但是我们总不能就是为了在地图上一通乱点,让地图告诉我坐标吧!- -| 那也太LOW了!我们肯定是看到地图上有什么东西了,比较好奇,所以才去点哦。或者说,你搜索了什么,地图上加载出结果来,你去点,然后才弹出Popup效果。

        这便是我下一篇要说的:矢量图层,使用矢量图层加载来自数据库的内容,并配合popup,呈现出更强的能力!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值