OpenLayers 3 入門教程
摘要
OpenLayers 3對OpenLayers網絡地圖庫進行了根本的重新設計。版本2雖然被廣泛使用,但從JavaScript開發的早期發展階段開始,已日益現實出它的落后。 OL3已運用現代的設計模式從底層重寫。
最初的版本旨在支持第2版提供的功能,提供大量商業或免費的瓦片資源以及最流行的開源矢量數據格式。與版本2一樣,數據可以被任意投影。最初的版本還增加了一些額外的功能,如能夠方便地旋轉地圖以及顯示地圖動畫。
OpenLayers 3同時設計了一些主要的新功能,如顯示三維地圖,或使用WebGL快速顯示大型矢量數據集,這些功能將在以后的版本中加入。
目錄
基本概念 4
Map 4
View 4
Source 5
Layer 5
總結 6
Openlayers 3實踐 7
1 地圖顯示 7
1.1創建一副地圖 7
1.2 剖析你的地圖 8
1.3 Openlayers的資源 11
2 圖層與資源 12
2.1 網絡地圖服務圖層 12
2.2 瓦片緩存 14
2.3 專有柵格圖層(Bing) 18
2.4 矢量圖層 20
2.5 矢量影像 23
3 控件與交互 24
3.1 顯示比例尺 24
3.2 選擇要素 26
3.3 繪制要素 29
3.4 修改要素 31
4 矢量樣式 33
4.1矢量圖層格式 33
4.2矢量圖層樣式 35
4.3 設置矢量圖層的樣式 38
基本概念
Map
OpenLayers 3的核心部件是Map(ol.Map)。它被呈現到對象target容器(例如,包含在地圖的網頁上的div元素)。所有地圖的屬性可以在構造時進行配置,或者通過使用setter方法,如setTarget()。
<div id="map" style="width: 100%, height: 400px"></div>
<script>
var map = new ol.Map({target: 'map'});
</script>
View
ol. View負責地圖的中心點,放大,投影之類的設置。
一個ol.View實例包含投影projection,該投影決定中心center 的坐標系以及分辨率的單位,如果沒有指定(如下面的代碼段),默認的投影是球墨卡托(EPSG:3857),以米為地圖單位。
放大zoom 選項是一種方便的方式來指定地圖的分辨率,可用的縮放級別由maxZoom (默認值為28)、zoomFactor (默認值為2)、maxResolution (默認由投影在256×256像素瓦片的有效成都來計算) 決定。起始於縮放級別0,以每像素maxResolution 的單位為分辨率,后續的縮放級別是通過zoomFactor區分之前的縮放級別的分辨率來計算的,直到縮放級別達到maxZoom 。
map.setView(new ol.View({
center: [0, 0],
zoom: 2
}));
Source
OpenLayers 3使用ol.source.Source子類獲取遠程數據圖層,包含免費的和商業的地圖瓦片服務,如OpenStreetMap、Bing、OGC資源(WMS或WMTS)、矢量數據(GeoJSON格式、KML格式…)等。
var osmSource = new ol.source.OSM();
Layer
一個圖層是資源中數據的可視化顯示,OpenLayers 3包含三種基本圖層類型:ol.layer.Tile、ol.layer.Image 和 ol.layer.Vector。
ol.layer.Tile 用於顯示瓦片資源,這些瓦片提供了預渲染,並且由特定分別率的縮放級別組織的瓦片圖片網格組成。
ol.layer.Image用於顯示支持渲染服務的圖片,這些圖片可用於任意范圍和分辨率。
ol.layer.Vector用於顯示在客戶端渲染的矢量數據。
var osmLayer = new ol.layer.Tile({source: osmSource});
map.addLayer(osmLayer);
總結
上述片段可以合並成一個自包含視圖和圖層的地圖配置:
<div id="map" style="width: 100%, height: 400px"></div>
<script>
new ol.Map({
layers: [
new ol.layer.Tile({source: new ol.source.OSM()})
],
view: new ol.View({
center: [0, 0],
zoom: 2
}),
target: 'map'
});
</script>
Openlayers 3實踐
1 地圖顯示
1.1創建一副地圖
在openlayers中,Map是圖層、各種交互以及處理用戶交互控件的集合,地圖由三個基本成分生成:標記,樣式聲明和初始化代碼。以下是一個完整的OpenLayers3地圖示例。
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
</style>
<title>OpenLayers 3 example</title>
<script src="ol3/ol.js" type="text/javascript"></script>
</head>
<body>
<h1>My Map</h1>
<div id="map"></div>
<script type="text/javascript">
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 0,
maxResolution: 0.703125
})
});
</script>
</body>
</html>
(1) 下載https://github.com/openlayers/ol3-workshop/archive/resources.zip,並將該文件夾放在網絡服務器的根目錄下;
(2) 創建一個新的文件,命名為map.html,將以上代碼復制進該文件后放入下載的文件夾的根目錄下;
(3) 在瀏覽器中輸入:http://localhost:8000/ol_workshop/map.html,我們將打開一個工作的地圖。
成功地創建了第一張地圖,我們將繼續關注地圖的組成部分,詳見1.2 。
1.2 剖析你的地圖
正如前一部分演示的那樣,一副地圖通過將標記,樣式聲明和初始化代碼三部分組織在一起而生成,接下來將詳細的介紹這三個組成部分。
1.2.1 地圖標記
標記為上例中的地圖生成的一個文檔元素:
<div id="map"></div>
在此示例中,我們用<div>元素作為地圖顯示的容器,其他塊級元素也能做視圖的容器。在這種情況下,我們設置容器的id屬性,所以我們可以將其作為地圖的對象。
1.2.2 地圖樣式
OpenLayers帶有一個默認的樣式表,指定地圖相關的元素應如何顯示,我們明確的將樣式表引用到map.html頁面中。
OpenLayers不對地圖的大小做預定義,因此在默認樣式表之后,我們需要包括至少一個自定義樣式聲明來說明地圖在頁面上的空間。
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
</style>
在該示例中,我們使用地圖容器的id值作為選擇器,並明確定義地圖容器的高為256px,寬為512px。樣式聲明直接包含在文檔的<head>部分。在大多數情況下,地圖相關的樣式說明是鏈接到外部樣式表的一個大型主題網站的一部分。
1.2.3 地圖初始化
生成地圖的下一步包含一些初始化代碼,在該示例中,我們在文檔的<body>前添加<script> 元素來實現。
<script>
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 0,
maxResolution: 0.703125
})
});
</script>
注:這些步驟的順序很重要,OpenLayers庫必須在在自定義腳本執行之前加載,在此示例中,OpenLayers庫在文檔的<head>部分加載(<script src="ol3/ol.js"></script>)。同樣的,在文檔中作為顯示容器的元素(該實例中為<div id="map"></div>)准備好之前,自定義地圖初始化代碼是不能執行的,將初始化代碼添加到文檔中<body>的后面,我們能在地圖生成前,確保庫已加載,顯示容器已准備好。
接下來,將詳細介紹初始化腳本的內容。腳本創建了一個包含一些配置選項的ol.Map對象:
target: 'map'
我們使用顯示容器的id屬性來告訴地圖構造函數將地圖交付到何處,在該示例中,我們通過字符串“map”作為地圖構造函數的對象。這個語法方便快捷,也可以更詳細的使用元素的直接引用(e.g. document.getElementById("map"))。
圖層配置創建了一個顯示在地圖中的圖層:
layers: [
new ol.layer.Tile({
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
})
],
不用擔心對以上的語法不了解,圖層創建在后續章節中會有詳細的介紹。最重要的是理解地圖顯示的是圖層的集合。為了顯示一副地圖,至少需要添加一個圖層。
最后一步是定義視圖,指定投影、中心點,放大級別,在該示例中,還指定了maxResolution,以確保請求的范圍不超過GeoWebCache能處理的范圍。
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 0,
maxResolution: 0.703125
})
以上,成功剖析了一副地圖的顯示,接下來將介紹更多關於OpenLayers的開發。
1.3 Openlayers的資源
OpenLayers 庫提供豐富的功能,盡管開發者對每個功能都提供了示例,並且讓其他有經驗的程序員找到屬於他們自己的方式來組織代碼,很多用戶仍覺得從頭開始是一個挑戰。
1.3.1 通過示例學習
新用戶很可能會發現研究OpenLayer的示例代碼以及庫的功能是開始起步最有效的方式。
• http://openlayers.org/en/master/examples/
1.3.2查看API參考
在理解了構成以及控制一幅地圖的基本組成之后,搜索API幫助文檔以了解方法簽名、對象屬性的詳細信息。
• http://openlayers.org/en/master/apidoc/
2 圖層與資源
2.1 網絡地圖服務圖層
當向地圖中添加圖層,圖層的資源通常用來獲取將要顯示的數據,數據請求可以是影像數據,也可以是矢量數據。柵格數據是服務端提供的圖片信息,矢量數據是服務器交付的結構化信息,在客戶端(瀏覽器)進行顯示。
有許多不同類型的服務提供柵格地圖數據,這部分涉及到符合OGC網絡地圖服務(WMS)規范的供應商。
2.1.1 創建圖層
在1.1 創建的地圖示例的基礎上,修改圖層來理解其運行機制。
layers: [
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
})
]
完整示例代碼詳見1.1。
2.1.2 The ol.layer.Tile構造函數
在1.1創建的示例中,使用的數據資源是ol.source.TileWMS,我們可以從title關鍵字的字面上理解它的含義,但是基本上來說,這里的關鍵字可以是任意名稱,在OpenLayers 3中,圖層和資源有一個區別,而在OpenLayers 2中,這兩部分一起組成了一個圖層。
ol.layer.Tile表示圖像的規則網格,而ol.layer.Image表示單個圖像,基於圖層類型,我們將使用不同的資源(ol.source.TileWMS與ol.source.ImageWMS)。
2.1.3 The ol.source.TileWMS構造函數
url指向的是WMS服務的在線資源,params是對象參數名稱及其值,由於在OpenLayers中,默認WMS版本是1.3.0,如果WMS不支持該版本,需要在params中提供一個低版本。
(1) 該示例中WMS提供了一個名為“openstreetmap”的圖層,將LAYERS 參數的值由“bluemarble”改為“openstreetmap”,代碼如下:
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'openstreetmap', VERSION: '1.1.1'}
})
})
(2) 改變圖層與資源,用單一圖像取代瓦片,再這個過程中,需要將資源的url修改為 http://suite.opengeo.org/geoserver/wms,將LAYERS 參數的值修改為“opengeo:countries”,完成修改后,利用瀏覽器的開發工具,確保請求的是單一圖像而不是256×256像素的瓦片。
了解了從網絡地圖服務動態獲取數據的機制,接下來將深入了解瓦片緩存服務。
2.2 瓦片緩存
默認情況在,瓦片圖層請求一個256×256像素的圖像來填充地圖視窗,當你平移或縮放地圖,將發出更多圖片請求來填充你沒有訪問過的地方。瀏覽器會緩存一些請求的圖像,這通常需要大量的處理器來動態渲染圖像。
由於瓦片圖層以規律的網格請求圖像,這使得服務器能夠緩存這些圖片請求並且在下次瀏覽相同區域的時候返回該緩存結果,從而獲得更好的性能。
2.2.1 ol.source.XYZ
網絡地圖服務規范使得客戶端能夠請求的內容具有靈活性,如果沒有限制,在實踐中,緩存會變得困難甚至不可能實現。
另一種幾段情況是,服務器可能只提供固定縮放級別和規律網格的瓦片,這種情況可以概括為XYZ資源的瓦片圖層——X/Y代表網格的行與列,Z代表縮放級別。
2.2.2 ol.source.OSM
OpenStreetMap (OSM)投影是為了收集並免費提供世界地圖的數據,OSM提供了一些不同的數據渲染作為瓦片緩存集,這些渲染符合基本的XYZ網格配置,並且可以在OpenLayers地圖中使用。ol.source.OSM圖層可以訪問OpenStreetMap瓦片資源。
(1) 打開1.1創建的map.html文件,將地圖初始化代碼替換為以下代碼:
<script>
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.transform([-93.27, 44.98], 'EPSG:4326', 'EPSG:3857'),
zoom: 9
}),
controls: ol.control.defaults({
attributionOptions: {
collapsible: false
}
})
});
</script>
(2) 在文檔的<head>中,添加以下圖層屬性的樣式說明:
<style>
#map {
width: 512px;
height: 256px;
}
.ol-attribution a {
color: black;
}
</style>
(3) 保存修改,在瀏覽器中查看該頁面:http://localhost:8000/ol_workshop/map.html:
2.2.2.1 投影
回顧地圖的視圖定義:
view: new ol.View({
center: ol.proj.transform([-93.27, 44.98], 'EPSG:4326', 'EPSG:3857'),
zoom: 9
})
地理空間數據可能來自各種坐標參照系,一個數據集可能是以度為單位的地理(經緯)坐標系,另一個可能是以米為單位的投影坐標系,對坐標系的全面討論超出了本實踐的范圍,但了解其基本概念是很重要的。
OpenLayers 3需要知道所使用數據的坐標系,在內部,由ol.proj.Projection對象展現,ol.proj命名空間中的transform 方法使用字符串表示坐標參考系(上述示例中的"EPSG:4326"以及"EPSG:3857")。
OpenStreetMap 瓦片數據是墨卡托投影,因此,我們需要使用墨卡托坐標了設置初始化時的中心點。由於一個地方的地理坐標相對來說更容易知道,使用ol.proj.transform方法將地理坐標系("EPSG:4326")轉化為墨卡托坐標系("EPSG:3857")。
OpenLayers 3包含地理坐標系與墨卡托坐標系間相互轉換的方法,因此我們可以使用ol.proj.transform方法而不需要任何額外的工作。如果想要使用其他投影的數據,再使用ol.proj.transform方法之前需要添加一些額外的信息。
例如,使用"EPSG:21781" 坐標參照系的數據,添加以下兩條script標簽到頁面中:
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/2.2.1/proj4.js"
type="text/javascript"></script>
<script src="http://epsg.io/21781-1753.js" type="text/javascript"></script>
然后在應用程序代碼中,注冊該投影並設置其有效范圍,代碼如下:
// This creates a projection object for the EPSG:21781 projection
// and sets a "validity extent" in that projection object.
var projection = ol.proj.get('EPSG:21781');
projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]);
2.2.2.2 圖層創建
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
之前的示例中,創建一個新圖層后,將其添加到地圖配置對象的圖層數組中,以上代碼接受資源的所有默認選項。
2.2.2.3 樣式
.ol-attribution a {
color: black;
}
如何處理地圖控件是本章節意外的內容,但是這里的樣式聲明讓你先睹為快。默認情況下ol.control.Attribution控件被添加到所有地圖中,這使得地圖視窗中顯示圖層資源的歸屬信息來源,上述聲明改變了地圖中歸屬信息的樣式(版權行再地圖的右下方)。
掌握了公開可用的緩存瓦片集的圖層用法,接下來將介紹專有的柵格圖層,詳見2.3 。
2.2.2.4 屬性控件配置
默認情況下,ol.control.Attribution控件在頁面上添加了一個i(information)按鈕,點擊即可顯示歸屬地信息。為了符合OpenStreetMap的使用條款,並且將OpenStreetMap的歸屬地信息一直展現出來,可添加以下代碼在ol.Map構造函數中最為可選對象。
controls: ol.control.defaults({
attributionOptions: {
collapsible: false
}
})
這段代碼移除了i按鈕,使得歸屬地信息一直展現在視圖中。
2.3 專有柵格圖層(Bing)
在前面的章節中,圖層是基於符合標准的WMS以及自定義瓦片緩存顯示的,在線地圖(或者瓦片地圖客戶端)主要是通過可用的專有地圖瓦片服務進行廣泛推廣,OpenLayers提供的圖層類型能通過使用它們的API來調用這些專有服務。
本章節使用的示例,是在上一章節示例的基礎上,添加一個使用Bing瓦片的圖層。
(1) 將map.html文件中配置OSM資源的代碼替換為ol.source.BingMaps:
source: new ol.source.BingMaps({
imagerySet: 'Road',
key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3'
})
注:Bing瓦片API要求用戶注冊一個API密鑰,該密鑰將在地圖應用程序中使用,示例中的
密鑰不能再產品中使用。
(1) 保存修改,在瀏覽器中查看該頁面:http://localhost:8000/ol_workshop/map.html:
完整示例代碼如下:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
.ol-attribution a {
color: black;
}
</style>
<script src="ol3/ol.js" type="text/javascript"></script>
<title>OpenLayers 3 example</title>
</head>
<body>
<h1>My Map</h1>
<div id="map" class="map"></div>
<script type="text/javascript">
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.BingMaps({
imagerySet: 'Road',
key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3'
})
})
],
view: new ol.View({
center: ol.proj.transform([-93.27, 44.98], 'EPSG:4326', 'EPSG:3857'),
zoom: 9
})
});
</script>
</body>
</html>
2.4 矢量圖層
矢量圖層由ol.layer.Vector展示,並處理客戶端矢量數據的顯示。以下將使用最初的WMS示例來獲取一個世界地圖,並在其基礎上添加一個帶有一些要素的矢量圖層。
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
</style>
<title>OpenLayers 3 example</title>
<script src="ol3/ol.js" type="text/javascript"></script>
</head>
<body>
<h1>My Map</h1>
<div id="map"></div>
<script type="text/javascript">
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 0,
maxResolution: 0.703125
})
});
</script>
</body>
</html>
2.4.1 添加矢量圖層
(1)打開map.html文件,將初始化WMS的示例復制其中,保存修改后在瀏覽器中確定地圖正常顯示:http://localhost:8000/ol_workshop/map.html。
(2)在地圖初始化代碼中,找到瓦片圖層的加載,在其后添加一下新的圖層,以下代碼實現請求一組存放在GeoJSON中的要素:
new ol.layer.Vector({
title: 'Earthquakes',
source: new ol.source.GeoJSON({
url: 'data/layers/7day-M2.5.json'
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 3,
fill: new ol.style.Fill({color: 'white'})
})
})
})
以上示例顯示 了世界地圖,附以白色的圓圈代表地震帶。
注:GeoJSON數據坐標系與地圖視圖的相同,均為EPSG:4326,因此無需再次設置投影,只有在資源與視圖的投影不同的情況下,才需要在資源中明確指定projection 屬性來表示要素緩存的投影,這以為着地圖視圖的投影通常可以被指定。
2.4.2 詳細說明
上述示例中,設置圖層的標題title為“Earthquakes”,使用ol.source.GeoJSON類型的資源source,該資源指向一個明確的url。
如果你希望要素的樣式基於其屬性,可以使用一個樣式函數替代ol.style.Style,從而配置ol.layer.Vector的樣式。
(1) 上述示例中地圖上白色的圓圈代表ol.layer.Vector圖層中的ol.Feature對象,每一個要素都包含title 和summary 屬性信息。地圖中注冊一個命名為forEachFeatureAtPixel的單擊監聽事件,並在地圖視圖下在顯示地震信息。
(2) 矢量圖層的數據來自於美國地質調查局(USGS)公布的地震資料(http://earthquake.usgs.gov/earthquakes/catalogs/),找到OpenLayers 3支持格式的矢量圖層信息保存為文檔,將該文檔放置在項目的data文件夾下,就能在地圖中顯示該矢量圖層。
2.5 矢量影像
在上一章節的示例中,使用了ol.layer.Vector類,在動態縮放的過程中,要素不斷重新渲染(點符號大小保持固定),在矢量圖層中,OpenLayers 基於每一動畫幀重新渲染資源數據,這使得在視圖的分辨率變化后,筆划、點符號、標簽持續的渲染。
另一種渲染策略是避免在視圖轉換的過程中重渲染,並將之前視圖的狀態下的渲染輸出重定位和改變其規模。通過使用包含ol.source.ImageVector的ol.layer.Image可以實現以上效果。這種結合,使得當視圖沒有動態變化時,保存渲染數據的“快照”,在視圖轉換過程中,重利用這些“快照”。
以下示例使用了包含ol.source.ImageVector的ol.layer.Image類,實現分塊渲染,使用該類可以僅渲染數據的一小部分,這種結合將適用於包含大量相對靜態數據渲染的應用程序。
2.5.1 ol.source.ImageVector
回顧2.4 添加的包含地震數據的地圖示例,將此示例改為分塊渲染,將矢量圖層替換為如下代碼:
new ol.layer.Image({
title: 'Earthquakes',
source: new ol.source.ImageVector({
source: new ol.source.GeoJSON({
url: 'data/layers/7day-M2.5.json'
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 3,
fill: new ol.style.Fill({color: 'white'})
})
})
})
})
通過以上方式,矢量數據由圖像描繪,但視覺上仍是要素的形式,實現了性能和質量之間本質的折中。
2.5.2 詳細說明
在上述代碼中,使用ol.layer.Image代替ol.layer.Vector,然而,仍可以通過ol.source.ImageVector連接原始的ol.source.GeoJSON類型數據,從而使用是矢量數據,這里的樣式提供了對ol.source.ImageVector的配置,而不是直接配置圖層。
3 控件與交互
3.1 顯示比例尺
比例尺是顯示在地圖上的典型窗口小部件,OpenLayers 3提供了ol.control.SaleLine來實現。
3.1.1創建比例尺
在地圖配置的范圍內,添加如下代碼,給地圖創建一個新的比例尺控件:
controls: ol.control.defaults().extend([
new ol.control.ScaleLine()
]),
一個默認的比例尺將出現在地圖視圖的左下角。
3.1.2 移動比例尺控件
如果覺得比例尺控件在圖形中看不清,一下提供幾種策略來提高比例尺的可見性。在文檔的CSS中添加一些樣式聲明,可以包括背景色,填充等,以下代碼可作為參考:
.ol-scale-line, .ol-scale-line:not([ie8andbelow]) {
background: black;
padding: 5px;
}
如果地圖視圖擁擠難耐,為了避免過度擁擠,可以將比例尺控件移到其他位置。實現此功能,需要在標記中創建一個額外元素來存放比例尺控件。
(1) 在map.html頁面的<body>范圍內創建一個新的塊級元素,為了更好的指向該元素,設置其id屬性scale-line,代碼如下:
<div id="scale-line" class="scale-line"></div>
將以上代碼放置在<div id="map"></div> 后最合理。
(2) 修改比例尺控件的創建代碼,使其指向scale-line元素:
controls: ol.control.defaults().extend([
new ol.control.ScaleLine({
className: 'ol-scale-line',
target: document.getElementById('scale-line')
})
]),
(3) 添加比例尺控件的樣式聲明:
.scale-line {
position: absolute;
top: 350px;
}
.ol-scale-line {
position: relative;
bottom: 0px;
left: 0px;
}
保存修改,在瀏覽器中查看該頁面:http://localhost:8000/ol_workshop/map.html:
實現比例尺控件在地圖視圖以外。
注:想要創建自定義控件,可以從ol.control.Control繼承(通過使用ol.inherits)。
3.2 選擇要素
矢量數據服務的一大優點是,用戶可以和數據交互,在本節示例中,將創建一個矢量圖層,用戶可以選擇和查看要素信息。
之前的示例展示了ol.control.Control的用法,控件可以在地圖上直接顯示,或者在文檔中添加一個DOM元素,ol.interaction.Interaction負責處理用戶交互,但是通常沒有視覺上的展現。一下示例將展示ol.interaction.Select的使用,實現與矢量圖層上的要素交互。
回顧2.4 中矢量圖層的創建,在其基礎上,添加選擇交互工具,完整代碼如下:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
</style>
<script src="ol3/ol.js" type="text/javascript"></script>
<title>OpenLayers 3 example</title>
</head>
<body>
<h1>My Map</h1>
<div id="map"></div>
<script type="text/javascript">
var map = new ol.Map({
interactions: ol.interaction.defaults().extend([
new ol.interaction.Select({
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: '#FF0000'
}),
stroke: new ol.style.Stroke({
color: '#000000'
})
})
})
})
]),
target: 'map',
layers: [
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
}),
new ol.layer.Vector({
title: 'Earthquakes',
source: new ol.source.GeoJSON({
url: 'data/layers/7day-M2.5.json'
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: '#0000FF'
}),
stroke: new ol.style.Stroke({
color: '#000000'
})
})
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 1
})
});
</script>
</body>
</html>
保存修改,在瀏覽器中打開:http://localhost:8000/ol_workshop/map.html.使用鼠標點擊事件選擇地震帶,查看要素選擇的效果。
3.3 繪制要素
通過使用ol.interaction.Draw可以繪制新的要素,一個繪制交互工具由矢量資源和幾何類型構成。
回顧2.4 中矢量圖層的創建,在其基礎上,添加繪制交互工具,完整代碼如下:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
</style>
<script src="ol3/ol.js" type="text/javascript"></script>
<title>OpenLayers 3 example</title>
</head>
<body>
<h1>My Map</h1>
<div id="map"></div>
<script type="text/javascript">
var source = new ol.source.GeoJSON({
url: 'data/layers/7day-M2.5.json'
});
var draw = new ol.interaction.Draw({
source: source,
type: 'Point'
});
var map = new ol.Map({
interactions: ol.interaction.defaults().extend([draw]),
target: 'map',
layers: [
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
}),
new ol.layer.Vector({
title: 'Earthquakes',
source: source,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: '#0000FF'
}),
stroke: new ol.style.Stroke({
color: '#000000'
})
})
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 1
})
});
</script>
</body>
</html>
保存修改,在瀏覽器中打開:http://localhost:8000/ol_workshop/map.html.點擊地圖來添加新的要素,實現點幾何對象的繪制。
3.4 修改要素
修改要素需要聯合使用ol.interaction.Select和ol.interaction.Modify,它們有一個共同的要素集(ol.Collection)。ol.interaction.Modify對ol.interaction.Select選擇的要素進行修改。
回顧2.4 中矢量圖層的創建,在其基礎上,添加選擇與修改交互工具,完整代碼如下:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
height: 256px;
width: 512px;
}
</style>
<script src="ol3/ol.js" type="text/javascript"></script>
<title>OpenLayers 3 example</title>
</head>
<body>
<h1>My Map</h1>
<div id="map"></div>
<script type="text/javascript">
var source = new ol.source.GeoJSON({
url: 'data/layers/7day-M2.5.json'
});
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: [0, 153, 255, 1]
}),
stroke: new ol.style.Stroke({
color: [255, 255, 255, 0.75],
width: 1.5
})
}),
zIndex: 100000
});
var select = new ol.interaction.Select({style: style});
var modify = new ol.interaction.Modify({
features: select.getFeatures()
});
var map = new ol.Map({
interactions: ol.interaction.defaults().extend([select, modify]),
target: 'map',
layers: [
new ol.layer.Tile({
title: "Global Imagery",
source: new ol.source.TileWMS({
url: 'http://maps.opengeo.org/geowebcache/service/wms',
params: {LAYERS: 'bluemarble', VERSION: '1.1.1'}
})
}),
new ol.layer.Vector({
title: 'Earthquakes',
source: source,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: '#0000FF'
}),
stroke: new ol.style.Stroke({
color: '#000000'
})
})
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [0, 0],
zoom: 1
})
});
</script>
</body>
</html>
保存修改,在瀏覽器中打開:http://localhost:8000/ol_workshop/map.html.使用鼠標點擊事件選擇地震帶,拖動該點,實現要素修改。
4 矢量樣式
4.1矢量圖層格式
基礎的ol.layer.Vector構造函數提供了一個相對固定的圖層類型,默認情況下,當創建一個新的矢量圖層時,並不知道圖層的要素來源,因為這是的ol.source.Vector內容。接下來將介紹自定義渲染風格,以及矢量數據的基本格式。
4.1.1 ol.format
OpenLayers 3中的ol.format類負責解析服務器中代表是兩要素的數據,大多數情況下,不會直接使用該類,但是會使用其相應的資源(比如:ol.source.KML)。該格式將原始要素數據轉變為ol.Feature對象。
考慮以下兩個數據塊,它們都表示同一個ol.Feature對象(西班牙巴塞羅那的一個點)。第一種序列化為GeoJSON(使用ol.format.GeoJSON解析),第二種序列化為KML(使用ol.format.KML解析)。
(1)GeoJSON Example
{
"type": "Feature",
"id": "OpenLayers.Feature.Vector_107",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [-104.98, 39.76]
}
}
(2)KML Example
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Placemark>
<Point>
<coordinates>-104.98,39.76</coordinates>
</Point>
</Placemark>
</kml>
4.2矢量圖層樣式
設置HTML元素樣式,使用如下CSS:
.someClass {
background-color: blue;
border-width: 1px;
border-color: olive;
}
.someClass是一個選擇器(選擇所有Class屬性值為"someClass"的對象),后面的內容是一組已命名的屬性與其對應的值,稱之為樣式聲明。
4.2.1 基礎樣式
一個矢量圖層可以有樣式,更明確的說法是,一個矢量圖層可以由一個ol.style.Style對象、一組ol.style.Style對象或者一個返回值為一組ol.style.Style對象的方法配置。
(1)由靜態樣式配置的矢量圖層:
var layer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style({
// ...
})
});
(2)由樣式方法配置的矢量圖層,將所有Class屬性值為"someClass"的對象設置為同一樣式:
var layer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: function(feature, resolution) {
if (feature.get('class') === 'someClass') {
// create styles...
return styles;
}
},
});
4.2.2 符號化
OpenLayers 3中的符號化相當於CSS中聲明的塊(下面是關於ol.style.*的典型示例)。在一個藍色的背景下用1像素寬的線條繪制區要素,將運用的如下兩個符號化對象:
new ol.style.Style({
fill: new ol.style.Fill({
color: 'blue'
}),
stroke: new ol.style.Stroke({
color: 'olive',
width: 1
})
});
不同的符號化對象使用於不同的幾何類型,區可以由線組成,但沒有填充,點可以用ol.style.Circle和ol.style.Icon進行樣式說明。前者呈現圓形的形狀,后者使用文件中的圖片(比如:png圖像)。下面是用圓形樣式的示例:
new ol.style.Circle({
radius: 20,
fill: new ol.style.Fill({
color: '#ff9900',
opacity: 0.6
}),
stroke: new ol.style.Stroke({
color: '#ffcc00',
opacity: 0.4
})
});
4.2.3 ol.style.Style
一個ol.style.Style對象有四個關鍵屬性:fill, image, stroke 和 text,外加一個zIndex屬性選項。下面的樣式方法將返回一組ol.style.Style對象。
以下示例實現將class 屬性值為的"someClass"對象中的要素設置為1像素寬的藍色,其余所有要素設置為紅色。(最好將樣式方法在對象外創建,以便重用,但以下代碼為簡單起見,將方法寫在對象內。)
style: (function() {
var someStyle = [new ol.style.Style({
fill: new ol.style.Fill({
color: 'blue'
}),
stroke: new ol.style.Stroke({
color: 'olive',
width: 1
})
})];
var otherStyle = [new ol.style.Style({
fill: new ol.style.Fill({
color: 'red'
})
})];
return function(feature, resolution) {
if (feature.get('class') === "someClass") {
return someStyle;
} else {
return otherStyle;
}
};
}())
注:一個要素也有樣式配置選項,只需設置resolution 參數就能實現對個別要素的樣式設置(基於分辨率)。
4.2.4 偽類
CSS允許選擇器中存在偽類,這限制了基於上下文的樣式聲明的應用,使得樣式聲明不容器在選擇器中表示,比如鼠標位置,附近的元素或者瀏覽器歷史。在OpenLayers 3中,有一種類似的概念:在ol.interaction.Select中添加樣式配置選項,示例代碼如下:
var select = new ol.interaction.Select({
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255,255,255,0.5)'
})
})
});
了解了基礎的樣式,接下來將介紹矢量圖層的樣式設置。
4.3 設置矢量圖層的樣式
本節示例將展示矢量圖層中的建築平面圖,完整示例代碼如下:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="ol3/ol.css" type="text/css">
<style>
#map {
background-color: gray;
height: 256px;
width: 512px;
}
</style>
<title>OpenLayers 3 example</title>
<script src="ol3/ol.js" type="text/javascript"></script>
</head>
<body>
<h1>My Map</h1>
<div id="map"></div>
<script type="text/javascript">
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Vector({
title: 'Buildings',
source: new ol.source.KML({
url: 'data/layers/buildings.kml',
extractStyles: false
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({color: 'red', width: 2})
})
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [-122.791859392, 42.3099154789],
zoom: 16
})
});
</script>
</body>
</html>
在瀏覽器中打開map.html文件:http://localhost:8000/ol_workshop/map.html,將看到帶有紅色輪廓的建築群。
創建一個樣式方法,根據面積的大小,使建築顯示為不同的顏色,將一下代碼,將Buildings 圖層的樣式配置選項替換為如下代碼:
style: (function() {
var defaultStyle = [new ol.style.Style({
fill: new ol.style.Fill({color: 'navy'}),
stroke: new ol.style.Stroke({color: 'black', width: 1})
})];
var ruleStyle = [new ol.style.Style({
fill: new ol.style.Fill({color: 'olive'}),
stroke: new ol.style.Stroke({color: 'black', width: 1})
})];
return function(feature, resolution) {
if (feature.get('shape_area') < 3000) {
return ruleStyle;
} else {
return defaultStyle;
}
};
})()
保存修改,在瀏覽器中查看:http://localhost:8000/ol_workshop/map.html。
最后給建築添加標簽,為了簡單化,我們使用黑色輪廓的樣式,並只使用一種標簽。
style: (function() {
var stroke = new ol.style.Stroke({
color: 'black'
});
var textStroke = new ol.style.Stroke({
color: '#fff',
width: 3
});
var textFill = new ol.style.Fill({
color: '#000'
});
return function(feature, resolution) {
return [new ol.style.Style({
stroke: stroke,
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
text: feature.get('key'),
fill: textFill,
stroke: textStroke
})
})];
};
})()
保存修改,在瀏覽器中查看:http://localhost:8000/ol_workshop/map.html。