openlayers添加標注(含聚合標注)蛤肌、覆蓋物业簿、繪制路線

如何用openlayers加載手繪地圖可以看另一篇文章:http://www.reibang.com/p/0b4fd0173b56

一瘤礁、加載矢量標注及聚合標注

通常需要在地圖上標注出一些景點、建筑或者公共設施梅尤,可以選擇使用矢量標注或者聚合標注柜思。openlayers 添加矢量標注的原理是將標注添加到一個新建的矢量層上,再將矢量層添加到地圖上疊加顯示巷燥;聚合標注的原理同上赡盘,但它適用于標注的數(shù)據(jù)量非常大的場景,隨著層級的放大缰揪,會展示更多的標注陨享,縮小時,則將標注聚合顯示钝腺,能夠在大量加載標注時提高渲染性能抛姑。
1、矢量標注

矢量標注.png

// 引入的對象和方法
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)重疊.png

聚合標注效果.png

使用聚合標注后定硝,標注間隙過密甚至出現(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)容窖杀,如點擊地圖彈出對話信息框漓摩、地圖上的自定義按鈕等則使用覆蓋層更加合適。

點擊彈出對話框.png

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)
})
三掏湾、繪制路線

原理大致與添加矢量標注相同裹虫,都是添加在矢量圖層上,不過這里添加的是線對象融击。


路線.png
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
    });
},
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涩拙,一起剝皮案震驚了整個濱河市际长,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兴泥,老刑警劉巖工育,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異搓彻,居然都是意外死亡如绸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門旭贬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怔接,“玉大人,你說我怎么就攤上這事稀轨《笃辏” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵奋刽,是天一觀的道長瓦侮。 經(jīng)常有香客問我,道長佣谐,這世上最難降的妖魔是什么肚吏? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮狭魂,結果婚禮上罚攀,老公的妹妹穿的比我還像新娘党觅。我一直安慰自己,他們只是感情好坞生,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布仔役。 她就那樣靜靜地躺著,像睡著了一般是己。 火紅的嫁衣襯著肌膚如雪又兵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天卒废,我揣著相機與錄音沛厨,去河邊找鬼。 笑死摔认,一個胖子當著我的面吹牛逆皮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播参袱,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼电谣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抹蚀?” 一聲冷哼從身側響起剿牺,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎环壤,沒想到半個月后晒来,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡郑现,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年湃崩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片接箫。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡攒读,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出列牺,到底是詐尸還是另有隱情整陌,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布瞎领,位于F島的核電站泌辫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏九默。R本人自食惡果不足惜震放,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驼修。 院中可真熱鬧殿遂,春花似錦诈铛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恩静,卻和暖如春焕毫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驶乾。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工邑飒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人级乐。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓疙咸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親风科。 傳聞我的和親對象是個殘疾皇子撒轮,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容