如何用openlayers加載手繪地圖可以看另一篇文章:http://www.reibang.com/p/0b4fd0173b56
一瘤礁、加載矢量標注及聚合標注
通常需要在地圖上標注出一些景點、建筑或者公共設施梅尤,可以選擇使用矢量標注或者聚合標注柜思。openlayers 添加矢量標注的原理是將標注添加到一個新建的矢量層上,再將矢量層添加到地圖上疊加顯示巷燥;聚合標注的原理同上赡盘,但它適用于標注的數(shù)據(jù)量非常大的場景,隨著層級的放大缰揪,會展示更多的標注陨享,縮小時,則將標注聚合顯示钝腺,能夠在大量加載標注時提高渲染性能抛姑。
1、矢量標注
// 引入的對象和方法
import Vectors from 'ol/layer/Vector.js'
import { WMTS, Vector } from 'ol/source.js'
import Feature from 'ol/Feature'
import OlGeomPoint from 'ol/geom/Point'
import OlStyleStyle from 'ol/style/Style'
import OlStyleIcon from 'ol/style/Icon'
import Text from 'ol/style/Text'
import Fill from 'ol/style/Fill'
/*創(chuàng)建矢量標注
*@param{object} data 標注的數(shù)據(jù)
*/
createLabel(data) {
// 初始化標簽要素
let feature = new Feature({
geometry: new OlGeomPoint(fromLonLat([+data.lng, +data.lat])), // 標簽位置
name: data.name, // 標注顯示的文字
img: require('./../../assets/imgs/map_icon_location.png'), // 標注顯示的logo圖片
})
feature.setId(data.id) // 設置ID
feature.setStyle(this.createLabelStyle(feature)) // 設置標注樣式
let source = new Vector({}) // 初始化矢量數(shù)據(jù)源
source.addFeature(feature) // 將標簽要素添加至矢量數(shù)據(jù)源
let layer = new Vectors({ // 創(chuàng)建矢量圖層
source: source
})
this.map.addLayer(layer) // 將矢量圖層添加至地圖
}
/*創(chuàng)建標注樣式
*@param{object} feature 標注要素
*@return {object} 返回創(chuàng)建的標注樣式對象
*/
createLabelStyle(feature) {
//返回一個樣式
return new OlStyleStyle({
//圖標樣式
image: new OlStyleIcon({
anchor: [10, 18], //設置圖標偏移
scale: 0.6, // 圖標縮小顯示
anchorOrigin: 'top-right', //標注樣式的起點位置
anchorXUnits: 'pixels', //X方向單位:分數(shù)
anchorYUnits: 'pixels', //Y方向單位:像素
offsetOrigin: 'bottom-left', //偏移起點位置的方向
opacity: 0.9, //透明度
src: feature.get('img') //圖片路徑
}),
//文本樣式
text: new Text({
textAlign: 'center', //對齊方式
textBaseline: 'middle', //文本基線
font: 'normal 12px 微軟雅黑', //字體樣式
text: feature.get('name'), //文本內(nèi)容
offsetY: -25, // Y軸偏置
fill: new Fill({ //填充樣式
color: '#ffffff'
}),
backgroundFill: new Fill({ // 填充背景
color: asString([0, 0, 0, 0.6]),
}),
padding: [2, 5, 2, 5],
}),
// 設置層級
zIndex: 199
});
}
2艳狐、聚合標注
使用聚合標注后定硝,標注間隙過密甚至出現(xiàn)重合的問題得以解決,待用戶放大地圖后再加載更多的標注僵驰。
// 引入的對象和方法
import Cluster from 'ol/source/Cluster'
import { WMTS, Vector } from 'ol/source.js'
import Feature from 'ol/Feature'
import OlGeomPoint from 'ol/geom/Point'
import OlStyleStyle from 'ol/style/Style'
import OlStyleIcon from 'ol/style/Icon'
import Text from 'ol/style/Text'
import Fill from 'ol/style/Fill'
/*創(chuàng)建聚合標注
*@param{object} data 標注的數(shù)據(jù)
*/
createClusterLabel(data) {
// 初始化標簽要素
let feature = new Feature({
geometry: new OlGeomPoint(fromLonLat([+data.lng, +data.lat])), // 標簽位置
name: data.name, // 標注顯示的文字
img: require('./../../assets/imgs/map_icon_location.png'), // 標注顯示的logo圖片
})
feature.setId(data.id) // 設置ID
let source = new Vector({}) // 初始化矢量數(shù)據(jù)源
source.addFeature(feature) // 將標簽要素添加至矢量數(shù)據(jù)源
let cluster = new Cluster({ // 創(chuàng)建聚合標注對象
distance: 25, // 設置聚合標注的距離
source: source
})
let layer = new Vectors({ // 創(chuàng)建矢量圖層
source: cluster,
style: function(feature, resolutions) { // 這里可以參照上面的createLableStyle寫喷斋,聚合標注在feature中單獨設置的樣式不生效
return new OlStyleStyle({
image: new OlStyleIcon({
src: feature.values_.features[0].values_.img // 圖片路徑
...
})
...
})
}
})
this.map.addLayer(layer) // 將聚合標注添加至地圖
}
二、加載覆蓋物(場景:點擊標注彈出對話框)
openlayers 可以創(chuàng)建一個 Overlay 覆蓋層蒜茴,這個覆蓋層能夠展示自己寫的 html 內(nèi)容星爪,從而實現(xiàn)添加各種所需的覆蓋物。也可以通過這個方法來添加標注粉私,但覆蓋層添加的覆蓋物會影響地圖的拖動(即在覆蓋物上進行滑動操作時地圖無法響應顽腾,雖然可以通過設置 stopEvent 將滑動事件傳遞到地圖上,但這樣會導致在IOS端的覆蓋物無法進行點擊操作)诺核。
因此如果要添加可以點擊并且不影響地圖拖動的標注時抄肖,建議使用矢量層標注,而如果要展示自定義的一些內(nèi)容窖杀,如點擊地圖彈出對話信息框漓摩、地圖上的自定義按鈕等則使用覆蓋層更加合適。
1入客、加載覆蓋層
import Overlay from 'ol/Overlay.js'
/*創(chuàng)建覆蓋物
*/
addOverlay() {
this.overlay = new Overlay({
element: document.getElementById('overlay-dlg'), // 將自己寫的 html 內(nèi)容添加到覆蓋層管毙,html 內(nèi)容略
positioning: 'bottom-center', // 覆蓋層位置
autoPan: true, // 是否自動平移腿椎,當點擊時對話框超出屏幕邊距,會自動平移地圖使其可見
autoPanMargin: 20, // 設置自動平移邊距
offset: [0, -20], // 覆蓋層偏移起點的位置
className: 'overlay-test' // 覆蓋物在覆蓋層的類名
})
}
2夭咬、添加地圖點擊監(jiān)聽事件
/* 實現(xiàn)點擊標注后在對應位置彈出信息框啃炸, 拿到標注的 feature 除了設置經(jīng)緯度外,
還能通過其 id 向后臺接口獲取要展示的數(shù)據(jù)卓舵,再渲染到覆蓋層的對話框上南用,這里代碼給的比較簡要,
有需要的可根據(jù)具體業(yè)務結合這個思路自行擴充代碼 */
var content = ducoment.getElementsById('content')
this.map.on('singleclick', (e) => {
// 獲取點擊的標注
let features = this.map.forEachFeatureAtPixel(evt.pixel, function (feature, layerVetor) { return feature })
// 設置覆蓋物的經(jīng)緯度
this.overlay.setPosition([feature.values_.geometry.flatCoordinates[0], feature.values_.geometry.flatCoordinates[1]])
// 設置要顯示的信息
content.html = '點擊的 id 是' + feature.id_
// 將覆蓋物添加到地圖上
this.map.addOverlay(this.overlay)
})
三掏湾、繪制路線
原理大致與添加矢量標注相同裹虫,都是添加在矢量圖層上,不過這里添加的是線對象融击。
import OlGeomLine from 'ol/geom/LineString'
/*繪制路線
*@param{array} routeList 路線數(shù)據(jù)
*/
createLineStroke(routeList) {
this.lineFeature = new Vector({}) // 創(chuàng)建路線矢量數(shù)據(jù)源
for(let i = 0; i < routeList.length; i++) { // 注意我這里是同時繪制多條路線
let polyLine = routeList[i].polyline.split(';')
let polyLintArray = []
polyLine.forEach(item => { // 處理接口傳過來的路徑數(shù)據(jù)恒界,轉(zhuǎn)換為 openlayers 所需的經(jīng)緯度數(shù)據(jù)格式
item = item.split(',')
item = fromLonLat([+item[0], +item[1]])
polyLintArray.push(item)
})
let feature = new Feature({ // 創(chuàng)建路線屬性
type: 'route',
geometry: new OlGeomLine(polyLintArray)
})
feature.setStyle(this.createLineStyle(i + 1))
// 添加路線箭頭,不需要繪制箭頭的可忽略
let img = require('./../../assets/imgs/icon_moer.png')
let style = [this.createLineStyle(i + 1)]
let geometry = feature.getGeometry()
let k = 0
geometry.forEachSegment((start, end) => {
k++
if (k % 50 !== 0) {
return
}
let dx = end[0] - start[0]
let dy = end[1] - start[1]
let rotation = Math.atan2(dy, dx) // 獲取子線段的角度
style.push(new OlStyleStyle({
geometry: new OlGeomPoint(end),
image: new OlStyleIcon({
scale: 0.6,
src: img,
anchor: [0.75, 0.5], // 圖標錨點
rotateWithView: true, // 與地圖視圖一起旋轉(zhuǎn)
// 設置子線段箭頭圖標樣式的角度
rotation: -rotation // 因為角度以順時針旋轉(zhuǎn)為正值砚嘴,所以前面添加負號
}),
zIndex: 200,
}))
})
feature.setStyle(style)
this.lineFeature.addFeature(feature) // 將路線屬性添加至矢量數(shù)據(jù)源中
}
this.lineLayer = new Vectors({ // 將路線矢量數(shù)據(jù)源添加至矢量層
source: this.lineFeature
})
this.map.addLayer(this.lineLayer) // 將矢量層添加到地圖
}
/*創(chuàng)建路線樣式
*@param{int} index 路線順序
*/
createLineStyle(index) {
//返回一個樣式
return new OlStyleStyle({
stroke: new Stroke({ // 路線填充樣式:寬度、顏色等
width: 8,
color: [16,168,218, 1],
}),
text: new Text({
text: '路段' + index, // 路線標簽文字
font: 'normal 12px 微軟雅黑', //字體樣式
fill: new Fill({ //文字填充樣式
color: [16,168,218, 1]
}),
backgroundFill: new Fill({
color: asString([255, 255, 255, 0.9]),
}),
padding: [1, 2, 1, 2],
}),
zIndex: 196
});
},