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.關于數(shù)據(jù)渲染的問題:
這里前端采用的是獲取左下角和右上角經(jīng)緯度作為參數(shù)傳遞給后臺獲取當前屏幕顯示的區(qū)域的數(shù)據(jù)。利用滑動地圖區(qū)域來請求接口渲染數(shù)據(jù),這樣就很好的解決了一次性加載很多的數(shù)據(jù)的問題。
文章內(nèi)容較長,花費時間需要一些時間,如果有疑問可留言、評論;以往也有發(fā)布關于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%);
}
/* 關閉彈窗按鈕 */
.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ù)
// constrainResolution: true,
//關閉無級縮放地圖
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打印的地方截圖:




到此這篇關于Vue結(jié)合openlayers按照經(jīng)緯度坐標實現(xiàn)錨地標記及繪制多邊形區(qū)域的文章就介紹到這了,更多相關Vue 繪制多邊形區(qū)域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- 在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ù)并顯示圖形效果
相關文章
Vue2仿淘寶實現(xiàn)省市區(qū)三級聯(lián)動
這篇文章主要為大家詳細介紹了Vue2仿淘寶實現(xiàn)省市區(qū)三級聯(lián)動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11
vue如何實現(xiàn)左右滑動tab(vue-touch)
這篇文章主要介紹了vue如何實現(xiàn)左右滑動tab(vue-touch),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
element ui提交表單返回成功后自動清空表單的值的實現(xiàn)代碼
這篇文章主要介紹了elementui提交表單返回成功后自動清空表單的值,本文通過兩種方法結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08

