Vue結(jié)合openlayers按照經(jīng)緯度坐標實現(xiàn)錨地標記及繪制多邊形區(qū)域
前言
本文介紹vue結(jié)合openlayers實現(xiàn)根據(jù)返回的經(jīng)緯度坐標完成錨地標記、繪制多邊形區(qū)域;
注意點:
1.根據(jù)返回的經(jīng)緯度取第一個坐標作為錨地圖標位置;
2.根據(jù)返回的經(jīng)緯度坐標數(shù)據(jù),這里的后臺數(shù)據(jù)需要處理(根據(jù)返回的數(shù)據(jù)處理成需要的格式),得到坐標數(shù)組渲染繪制區(qū)域畫圖顯示在航道圖層上。
3.關(guān)于數(shù)據(jù)渲染的問題:
這里前端采用的是獲取左下角和右上角經(jīng)緯度作為參數(shù)傳遞給后臺獲取當前屏幕顯示的區(qū)域的數(shù)據(jù)。利用滑動地圖區(qū)域來請求接口渲染數(shù)據(jù),這樣就很好的解決了一次性加載很多的數(shù)據(jù)的問題。
文章內(nèi)容較長,花費時間需要一些時間,如果有疑問可留言、評論;以往也有發(fā)布關(guān)于openlayers的其它文章,可在本博客訂閱搜索查看。
openlayers官方文檔學習:
實現(xiàn)效果圖預覽:
實現(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"; //默認縮放 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ù)需要的自己補充
data(){ // 地圖 map:null, cjinobeaconMap:null, //默認加載中心點 center: { longitude: "114.293726",//114.293726 113.306100 latitude: "30.577845",//30.577845 29.629998 }, anchorageIcon:require("../../assets/img/anchorage_icon.png"),//錨地圖標 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, // 彈窗標簽,在html里 autoPan: true, // 如果彈窗在底圖邊緣時,底圖會移動 autoPanAnimation: { // 底圖移動動畫 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 // 移動端禁止地圖旋轉(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è)置縮放級別為整數(shù) // constrainResolution: true, //關(guān)閉無級縮放地圖 smoothResolutionConstraint: false }) }); this.mapClick(); // 初始化地圖成功后,給地圖添加點擊事件 this.map.addEventListener("moveend", this.showView);//監(jiān)聽地圖區(qū)域滑動 },
動態(tài)顯示圖層
showView() { let zoom = this.map.getView().getZoom(); console.log(zoom,"縮放") this.map.getLayers().getArray().forEach((item) => { if (item.get("name") == "anchorageVectorLayer") { // 錨地,這里根據(jù)獲取的層級顯示隱藏數(shù)據(jù) if (zoom>13) { item.setVisible(true); this.getAnchorageData(); } else { this.shopPopup = false; item.setVisible(false); this.map.removeLayer(this.mdVectorLayer);//錨地圖標 } } }); },
彈窗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對象集合中的 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當前坐標"); 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.錨地數(shù)據(jù)獲取
重要代碼
// 獲取錨地數(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; }); //取第一個坐標 const selectOneData = res.data.map(item=>{ return item.lonAndLatDatas[0]; }); const selectOneName = res.data.map(item=>{ return item.anchorageName; }); console.log(selectOneName,"取第一個坐標名字"); // 添加圖標 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庫偏向方向正好相反 }), }) ); }); 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)緯度坐標實現(xiàn)錨地標記及繪制多邊形區(qū)域的文章就介紹到這了,更多相關(guān)Vue 繪制多邊形區(qū)域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 在Vue?3中使用OpenLayers加載GPX數(shù)據(jù)并顯示圖形效果
- vue+openlayers+nodejs+postgis實現(xiàn)軌跡運動效果
- Vue使用openlayers加載天地圖
- Vue+OpenLayers?創(chuàng)建地圖并顯示鼠標所在經(jīng)緯度(完整代碼)
- vue?openlayers實現(xiàn)臺風軌跡示例詳解
- vue利用openlayers實現(xiàn)動態(tài)軌跡
- Vue openLayers實現(xiàn)圖層數(shù)據(jù)切換與加載流程詳解
- Vue利用openlayers實現(xiàn)點擊彈窗的方法詳解
- Vue使用openlayers實現(xiàn)繪制圓形和多邊形
- 在Vue 3中使用OpenLayers讀取WKB數(shù)據(jù)并顯示圖形效果
相關(guān)文章
Vue 2.0入門基礎(chǔ)知識之內(nèi)部指令詳解
這篇文章主要介紹了Vue 2.0入門基礎(chǔ)知識之內(nèi)部指令知識,非常不錯,具有參考借鑒價值 ,需要的朋友可以參考下2017-10-10useEffect理解React、Vue設(shè)計理念的不同
這篇文章主要為大家介紹了useEffect理解React、Vue設(shè)計理念的不同詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09vite.config.ts配置之自動導入element-puls方式
這篇文章主要介紹了vite.config.ts配置之自動導入element-puls方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10Vue監(jiān)聽滾動實現(xiàn)錨點定位(雙向)示例
今天小編大家分享一篇Vue監(jiān)聽滾動實現(xiàn)錨點定位(雙向)示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11Vue項目打包部署到GitHub Pages的實現(xiàn)步驟
本文主要介紹了Vue項目打包部署到GitHub Pages的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04vue使用neovis操作neo4j圖形數(shù)據(jù)庫及優(yōu)缺點
這篇文章主要介紹了vue使用neovis操作neo4j圖形數(shù)據(jù)庫,本文給大家介紹了與常規(guī)做法的優(yōu)缺點對比及使用技巧,對vue?neo4j圖形數(shù)據(jù)庫相關(guān)知識感興趣的朋友一起看看吧2022-02-02