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