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ū)域畫(huà)圖顯示在航道圖層上。
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)畫(huà)
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"]
// ];
// 畫(huà)圖層
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入門(mén)基礎(chǔ)知識(shí)之內(nèi)部指令詳解
這篇文章主要介紹了Vue 2.0入門(mén)基礎(chǔ)知識(shí)之內(nèi)部指令知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值 ,需要的朋友可以參考下2017-10-10
useEffect理解React、Vue設(shè)計(jì)理念的不同
這篇文章主要為大家介紹了useEffect理解React、Vue設(shè)計(jì)理念的不同詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
vite.config.ts配置之自動(dòng)導(dǎo)入element-puls方式
這篇文章主要介紹了vite.config.ts配置之自動(dòng)導(dǎo)入element-puls方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
Vue項(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-04
Vue監(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-11
Vue項(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-04
vue3.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-10
vue使用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

