OpenLayers 3 之 彈出框(popup)
摘要
上回說到,載入完地圖後,我們想更多一點互動,而不僅僅是縮放和平移,賦予地圖多一點的生命 ~-~!點選地圖,它至少應該知道我是在哪裡點選了,並且彈出一個氣球類似的框框告訴我!這次,我們就來嘗試給我們的地圖加上這個能力!
PS:這次的例子是基於上一篇的載入地圖的程式碼的哦!在上一篇的基礎上增刪修改,所以讀讀前一篇是很有必要的哦!
正文
在OpenLayers2.x的那個年代 ~-~|,我們知道OpenLayers有一個類(Popup)是專門負責這項“彈出氣球”功能的。現在,到了3.x的時代,不同於OpenLayers 2.x,OpenLayers 3.x去除了Popup類,新增加了Overlay類,用於實現與Popup相同的彈出效果。在OpenLayers3.x的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,呈現出更強的能力!