Vue結(jié)合openlayers按照經(jīng)緯度坐標(biāo)實(shí)現(xiàn)錨地標(biāo)記及繪制多邊形區(qū)域
前言
本文介紹vue結(jié)合openlayers實(shí)現(xiàn)根據(jù)返回的經(jīng)緯度坐標(biāo)完成錨地標(biāo)記、繪制多邊形區(qū)域;
注意點(diǎn):
1.根據(jù)返回的經(jīng)緯度取第一個(gè)坐標(biāo)作為錨地圖標(biāo)位置;
2.根據(jù)返回的經(jīng)緯度坐標(biāo)數(shù)據(jù),這里的后臺(tái)數(shù)據(jù)需要處理(根據(jù)返回的數(shù)據(jù)處理成需要的格式),得到坐標(biāo)數(shù)組渲染繪制區(qū)域畫圖顯示在航道圖層上。
3.關(guān)于數(shù)據(jù)渲染的問(wèn)題:
這里前端采用的是獲取左下角和右上角經(jīng)緯度作為參數(shù)傳遞給后臺(tái)獲取當(dāng)前屏幕顯示的區(qū)域的數(shù)據(jù)。利用滑動(dòng)地圖區(qū)域來(lái)請(qǐng)求接口渲染數(shù)據(jù),這樣就很好的解決了一次性加載很多的數(shù)據(jù)的問(wèn)題。
文章內(nèi)容較長(zhǎng),花費(fèi)時(shí)間需要一些時(shí)間,如果有疑問(wèn)可留言、評(píng)論;以往也有發(fā)布關(guān)于openlayers的其它文章,可在本博客訂閱搜索查看。
openlayers官方文檔學(xué)習(xí):
實(shí)現(xiàn)效果圖預(yù)覽:
實(shí)現(xiàn)步驟:
1.安裝openlayers
cnpm i -S ol
#或者
npm install ol
2.引入模塊
// openlayers地圖 import "ol/ol.css"; import { Icon, Style ,Text,Fill,Stroke,Circle as CircleStyle} from "ol/style"; import Map from "ol/Map"; import View from "ol/View"; // import OSM from "ol/source/OSM"; import TileLayer from "ol/layer/Tile"; import XYZ from "ol/source/XYZ"; import { get as getProjection ,fromLonLat} from "ol/proj.js"; import { getBottomLeft, getTopRight } from "ol/extent.js"; import { Vector as SourceVec } from "ol/source"; import { Vector as LayerVec } from "ol/layer"; import Overlay from "ol/Overlay"; //彈窗 import { Point } from "ol/geom"; import { Feature } from "ol"; import Observable from 'ol/Observable'; import { defaults as defaultControls } from "ol/control"; //默認(rèn)縮放 import { FullScreen, ScaleLine, ZoomSlider } from "ol/control"; //全屏,比例尺控件 import TileGrid from "ol/tilegrid/TileGrid"; import { LineString, Polygon } from "ol/geom.js"; import {defaults as defaultInteractions} from 'ol/interaction';//旋轉(zhuǎn)
3.地圖與彈窗html樣式
<!-- 地圖 --> <div style="width:100%;height:100%"> <div id="mapDiv"></div> <!-- 彈窗元素 --> <div class="popup serchPopup" ref="popup" v-show="shopPopup" > <div class="ship-header"> <div class="cname">{{anchorageName?anchorageName:""}}</div> <img class="icon-close" @click="closePopup" src="../../assets/img/sy_close.png"/> </div> </div> </div>
/* 彈窗樣式 */ .popup { font-family: "微軟雅黑"; // min-width: 280px; position: relative; display: flex; flex-direction: column; transform: translate(-50%, calc(-100% - 12px)); opacity: 0.95; background: #ffffff; border-radius: 24px; box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.15); // overflow: hidden; .content { margin-top: 6px; } .ship-header { padding: 20px 30px; display: flex; justify-content: space-between; align-items: center; .cname { font-weight: 600; font-size: 32px; color: #024ee0; } } .ship-content { padding: 30px; border-top: 1px solid #ececec; font-size: 24px; font-weight: 500; color: #535f8b; .con-sx { display: flex; justify-content: space-between; .txt-margin { margin-right: 60px; } } } } /* 彈窗下方的小三角形 */ .serchPopup::after { display: block; content: ""; width: 0; height: 0; position: absolute; border: 12px solid transparent; border-top-color: #fff; bottom: -23px; left: 50%; transform: translateX(-50%); } /* 關(guān)閉彈窗按鈕 */ .icon-close { cursor: pointer; width: 24px; height: 24px; }
4.data數(shù)據(jù)定義
根據(jù)需要的自己補(bǔ)充
data(){ // 地圖 map:null, cjinobeaconMap:null, //默認(rèn)加載中心點(diǎn) center: { longitude: "114.293726",//114.293726 113.306100 latitude: "30.577845",//30.577845 29.629998 }, anchorageIcon:require("../../assets/img/anchorage_icon.png"),//錨地圖標(biāo) anchorageVector:false, anchorageVectorLayer:null, anchorageFeatures:[], drawSource: null, }
5.methods方法
初始化
initMap() { let defaultsMap = { tileUrl1:"圖層數(shù)據(jù)地址", origin: [-400, 400], zoom: 7, resolutions: [ //根據(jù)需求添加區(qū)域 ], fullExtent: [ //根據(jù)需求添加區(qū)域 ], inters: [1000, 100], center: [this.center.longitude, this.center.latitude], projection: getProjection("EPSG:4326") }; // 航道圖層 this.cjinobeaconMap = new TileLayer({ source: new XYZ({ tileGrid: tileGrid, projection: defaultsMap.projection, url: defaultsMap.tileUrl1 }), zIndex: 9 }); // 彈窗 this.overlay = new Overlay({ element: this.$refs.popup, // 彈窗標(biāo)簽,在html里 autoPan: true, // 如果彈窗在底圖邊緣時(shí),底圖會(huì)移動(dòng) autoPanAnimation: { // 底圖移動(dòng)動(dòng)畫 duration: 250 }, stopEvent: false, offset: [0, -10], className:"popupOverlay", }); // 加載地圖 this.map = new Map({ target: "mapDiv", controls: defaultControls().extend([ new FullScreen(), new ScaleLine({ units: "metric" }) // new ZoomSlider() ]), interactions: defaultInteractions({ pinchRotate: false // 移動(dòng)端禁止地圖旋轉(zhuǎn) }), loadTilesWhileAnimating: true, layers: [this.cjinobeaconMap],//保留航道圖層 overlays: [this.overlay], // 把彈窗加入地圖 view: new View({ projection: defaultsMap.projection, center: defaultsMap.center, center: [114.272172,30.564646], extent: defaultsMap.fullExtent, // resolutions: defaultsMap.resolutions, zoom: 14, // minZoom: 12, // maxZoom:17, //設(shè)置縮放級(jí)別為整數(shù) // constrainResolution: true, //關(guān)閉無(wú)級(jí)縮放地圖 smoothResolutionConstraint: false }) }); this.mapClick(); // 初始化地圖成功后,給地圖添加點(diǎn)擊事件 this.map.addEventListener("moveend", this.showView);//監(jiān)聽(tīng)地圖區(qū)域滑動(dòng) },
動(dòng)態(tài)顯示圖層
showView() { let zoom = this.map.getView().getZoom(); console.log(zoom,"縮放") this.map.getLayers().getArray().forEach((item) => { if (item.get("name") == "anchorageVectorLayer") { // 錨地,這里根據(jù)獲取的層級(jí)顯示隱藏?cái)?shù)據(jù) if (zoom>13) { item.setVisible(true); this.getAnchorageData(); } else { this.shopPopup = false; item.setVisible(false); this.map.removeLayer(this.mdVectorLayer);//錨地圖標(biāo) } } }); },
彈窗mapClick
// 彈窗 mapClick() { this.map.on("singleclick", evt => { this.isShowSerchList = false; let pixel = this.map.getEventPixel(evt.originalEvent); let feature = this.map.forEachFeatureAtPixel( evt.pixel, feature => feature ); if (feature) { console.log(feature,"feature") this.shipName = feature.values_.shipName; //Feature對(duì)象集合中的 this.portName = feature.values_.portName?feature.values_.portName:feature.values_.name;//港口 this.portId = feature.values_.portId; this.mmsi = feature.values_.mmsi; this.nature = feature.values_.nature; this.csx = feature.values_.csx; this.speed = feature.values_.speed; this.updateTime = feature.values_.updateTime; this.shipStatus=feature.values_.shipStatus; this.vipStatus=feature.values_.vipStatus; this.shipType = feature.values_.shipType; this.areaName = feature.values_.areaName; console.log(this.areaName,"this.areaName"); this.lonAndLatData = feature.values_.lonAndLatData; // 錨地名字 this.anchorageName = feature.values_.anchorageName; console.log(this.anchorageName,"this.anchorageName"); let coordinates = feature.getGeometry().getCoordinates(); console.log(coordinates, "coordinates當(dāng)前坐標(biāo)"); this.longitude = coordinates[0]; this.latitude = coordinates[1]; // 錨地 if(this.anchorageName){ setTimeout(() => { this.overlay.setPosition(coordinates); }, 0); } if(this.anchorageName){ this.shopPopup = true; }else{ this.shopPopup = false; } } else { this.shopPopup = false; } }); },
6.mounted數(shù)據(jù)加載
mounted(){ this.initMap(); //加載地圖 this.getAnchorageData();//錨地 }
7.錨地?cái)?shù)據(jù)獲取
重要代碼
// 獲取錨地?cái)?shù)據(jù) getAnchorageData(){ let arr = this.map.getView().calculateExtent(this.map.getSize());//獲取左下角和右上角經(jīng)緯度 let params = { leftLongitude: arr[0], leftLatitude: arr[1], rightLongitude: arr[2], rightLatitude: arr[3], } this.mdFeatures = []; this.mdMarker = []; homePageAnchorageData(params).then(res=>{ if(res.code == 200){ // // this.anchorageFeatures = res.data.map(item=>{ return item.lonAndLatDatas; }); //取第一個(gè)坐標(biāo) const selectOneData = res.data.map(item=>{ return item.lonAndLatDatas[0]; }); const selectOneName = res.data.map(item=>{ return item.anchorageName; }); console.log(selectOneName,"取第一個(gè)坐標(biāo)名字"); // 添加圖標(biāo) this.mdFeatures = selectOneData; this.mdFeatures.map((item, index) => { this.mdMarker.push( new Feature({ geometry: new Point([item[0], item[1]], "XY"), anchorageName:selectOneName[index], index: index }) ); }); let mdIconStyles = []; this.mdMarker.forEach(item => { mdIconStyles.push( new Style({ image: new Icon({ src: this.anchorageIcon, scale: 0.6, anchor: [0.5, 0.9],// 偏移的 x 與 y 方向值,注意此值與 Cesium 等GIS庫(kù)偏向方向正好相反 }), }) ); }); let mdVectorSource = new SourceVec({ features: this.mdMarker }); this.mdVectorLayer = new LayerVec({ name: "mdVectorLayer", source: mdVectorSource, style: (feature)=> { let iconStyle = mdIconStyles[feature.values_.index]; return [iconStyle]; }, zIndex: 13 }); this.map.addLayer(this.mdVectorLayer); this.mdVector = true; // this.anchorageFeatures = [ // ["113.306100", "29.629998"], // ["113.296623", "29.619303"], // ["113.294041", "29.620805"], // ["113.302937", "29.631876"] // ]; // 畫圖層 this.drawSource = new SourceVec({ wrapX: false }) this.anchorageVectorLayer = new LayerVec({ name: "anchorageVectorLayer", source: this.drawSource, style: function (feature) { let styles = [ new Style({ stroke: new Stroke({ width: 2, color: '#ff4e4e' }), fill: new Fill({ color: 'rgba(255, 78, 78, 0.2)' }), }) ] var geometry = feature.getGeometry() if (geometry instanceof LineString) { geometry.forEachSegment(function (start, end) { console.log(start,"start") styles.push(new Style({ geometry: new Point(start), image: new CircleStyle({ radius: 4, snapToPixel: false, fill: new Fill({ color: 'white' }), stroke: new Stroke({ color: '#FF0F0F', width: 2 }), }) })) }) } return styles }, zIndex:12 }); this.anchorageFeatures.forEach(item=>{ this.drawSource.addFeature(new Feature({ geometry: new Polygon([item]) })); }) this.map.addLayer(this.anchorageVectorLayer); this.anchorageVector = true; } }) },
console.log打印的地方截圖:
到此這篇關(guān)于Vue結(jié)合openlayers按照經(jīng)緯度坐標(biāo)實(shí)現(xiàn)錨地標(biāo)記及繪制多邊形區(qū)域的文章就介紹到這了,更多相關(guān)Vue 繪制多邊形區(qū)域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 在Vue?3中使用OpenLayers加載GPX數(shù)據(jù)并顯示圖形效果
- vue+openlayers+nodejs+postgis實(shí)現(xiàn)軌跡運(yùn)動(dòng)效果
- Vue使用openlayers加載天地圖
- Vue+OpenLayers?創(chuàng)建地圖并顯示鼠標(biāo)所在經(jīng)緯度(完整代碼)
- vue?openlayers實(shí)現(xiàn)臺(tái)風(fēng)軌跡示例詳解
- vue利用openlayers實(shí)現(xiàn)動(dòng)態(tài)軌跡
- Vue openLayers實(shí)現(xiàn)圖層數(shù)據(jù)切換與加載流程詳解
- Vue利用openlayers實(shí)現(xiàn)點(diǎn)擊彈窗的方法詳解
- Vue使用openlayers實(shí)現(xiàn)繪制圓形和多邊形
- 在Vue 3中使用OpenLayers讀取WKB數(shù)據(jù)并顯示圖形效果
相關(guān)文章
Vue 2.0入門基礎(chǔ)知識(shí)之內(nèi)部指令詳解
這篇文章主要介紹了Vue 2.0入門基礎(chǔ)知識(shí)之內(nèi)部指令知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值 ,需要的朋友可以參考下2017-10-10useEffect理解React、Vue設(shè)計(jì)理念的不同
這篇文章主要為大家介紹了useEffect理解React、Vue設(shè)計(jì)理念的不同詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09vite.config.ts配置之自動(dòng)導(dǎo)入element-puls方式
這篇文章主要介紹了vite.config.ts配置之自動(dòng)導(dǎo)入element-puls方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10Vue項(xiàng)目中使用jquery的簡(jiǎn)單方法
這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中使用jquery的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05解決vue內(nèi)存溢出報(bào)錯(cuò)的問(wèn)題
這篇文章主要介紹了解決vue內(nèi)存溢出報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue監(jiān)聽(tīng)滾動(dòng)實(shí)現(xiàn)錨點(diǎn)定位(雙向)示例
今天小編大家分享一篇Vue監(jiān)聽(tīng)滾動(dòng)實(shí)現(xiàn)錨點(diǎn)定位(雙向)示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11Vue項(xiàng)目打包部署到GitHub Pages的實(shí)現(xiàn)步驟
本文主要介紹了Vue項(xiàng)目打包部署到GitHub Pages的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04vue3.0中的watch偵聽(tīng)器實(shí)例詳解
雖然計(jì)算屬性在大多數(shù)情況下更合適,但有時(shí)也需要一個(gè)自定義的偵聽(tīng)器,這就是為什么Vue通過(guò)watch選項(xiàng)提供了一個(gè)更通用的方法,來(lái)響應(yīng)數(shù)據(jù)的變化,這篇文章主要給大家介紹了關(guān)于vue3.0中watch偵聽(tīng)器的相關(guān)資料,需要的朋友可以參考下2021-10-10vue使用neovis操作neo4j圖形數(shù)據(jù)庫(kù)及優(yōu)缺點(diǎn)
這篇文章主要介紹了vue使用neovis操作neo4j圖形數(shù)據(jù)庫(kù),本文給大家介紹了與常規(guī)做法的優(yōu)缺點(diǎn)對(duì)比及使用技巧,對(duì)vue?neo4j圖形數(shù)據(jù)庫(kù)相關(guān)知識(shí)感興趣的朋友一起看看吧2022-02-02