同步操作将从 st19911224/Vue-Openlayers 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
由于最近项目需要,需要在vue项目中使用OpenLayers来进行 GIS 地图的开发,网上对 OpenLayers 文章并不算太大,借此机会分享下自己在项目中实际使用的一些心得。
本系列将陆续分享项目过程中实现的一些功能点,本文主要介绍以下部分:
本项目基于 vue 开发,首先准备一个 vue 项目,直接 vue-cli 搭建一个就行,文章用项目版本为 vue2+sass
Openlayers 的 npm 包名为 ol,咱们直接在项目中引入 ol 就行
npm install ol
// or
yarn add ol
将初始文件默认路由的页面更改下
// app.vue
<template>
<div id="app">
<router-view />
</div>
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>
// Home.vue
<template>
<div class="home">
</div>
</template>
<script>
export default {
name: "Home",
components: {},
};
</script>
在 Home.vue 文件中进行 map 渲染,本文采用的是高德地图的切片地图模式,
// Home.vue
<template>
<div class="home">
<div id="map" class="map-home"></div>
</div>
</template>
<script>
import { Map, View } from "ol";
import * as olProj from "ol/proj";
import TileLayer from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";
export default {
name: "Home",
components: {},
data() {
return {
openMap: null,
};
},
mounted() {
this.initMap();
},
methods: {
initMap() {
this.openMap = new Map({
target: "map",
layers: [
new TileLayer({
source: new XYZ({
url: "https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",
}),
}),
],
view: new View({
// 将西安作为地图中心
center: olProj.fromLonLat([108.945951, 34.465262]),
zoom: 1,
}),
controls: [],
});
},
},
};
</script>
<style lang="scss" scoped>
.map-home {
width: 100vw;
height: 100vh;
}
</style>
基本类介绍,Openlayers 中 4 个主要的类:
此时运行项目已经能够看到地图展示了;
地图中最常见的需求就是做点位标记,同理,这时我们只需要在之前的地图 Layer 上再盖一层点位标记的 Layer 即可,使用的是 VectorLayer 跟 VectorSource,矢量图层以及一个矢量数据
import { Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
我们这里简单实现,直接将一个点位添加到 openMap 的 layers 数组里;
// import
import { Map, View, Feature } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
import * as olProj from "ol/proj";
import { Point } from "ol/geom";
import { Style, Fill, Stroke, Circle as sCircle } from "ol/style";
// methods添加setMarker方法
mounted() {
this.initMap();
this.setMarker();
},
// setMarker
setMarker() {
let _style = new Style({
image: new sCircle({
radius: 10,
stroke: new Stroke({
color: "#fff",
}),
fill: new Fill({
color: "#3399CC",
}),
}),
});
let _feature = new Feature({
geometry: new Point(olProj.fromLonLat([108.945951, 34.465262])),
});
_feature.setStyle(_style);
let _marker = new VectorLayer({
source: new VectorSource({
features: [_feature],
}),
});
this.openMap.addLayer(_marker);
},
成功在地图上添加了一个点位。
上方代码中 import 了几个新的类:Feature,Point,Style 等,主要是具有几何的地理要素的矢量对象以及具体的样式,然后通过 setStyle 将样式赋予 Feature,主要就在地图上绘制出了一个坐标点。
接下来咱们需要给 3 小节中的坐标点添加点击事件,同时能够在地图上显示一个弹框,展示点位的一些信息。
首先添加点击事件,这里使用单击 singleclick
singleclick() {
this.openMap.on("singleclick", (e) => {
// 判断是否点击在点上
let feature = this.openMap.forEachFeatureAtPixel(
e.pixel,
(feature) => feature
);
console.log(feature);
});
},
当我们没有点击在点上时,会打印 undefined,而点击在点上时会打印出对应的 feature 信息
这里我们同时添加一个事件 pointermove,改变鼠标移到到点位上的光标样式。
pointermove() {
this.openMap.on("pointermove", (e) => {
if (this.openMap.hasFeatureAtPixel(e.pixel)) {
this.openMap.getViewport().style.cursor = "pointer";
} else {
this.openMap.getViewport().style.cursor = "inherit";
}
});
},
接着上面的点击事件,当我们点击时希望能够在点位的上方显示出该点的信息弹窗
先在 vue 添加个弹窗组件,需要引入一个新的类 Overlay
import { Overlay } from "ol";
// template
<!-- 弹框 -->
<div ref="popup" class="popup" v-show="shopPopup">
<div class="info">
<ul>
<li>信息1:xxx</li>
<li>信息2:xxx</li>
<li>信息3:xxx</li>
</ul>
</div>
</div>
// script
addOverlay() {
// 创建Overlay
let elPopup = this.$refs.popup;
this.popup = new Overlay({
element: elPopup,
positioning: "bottom-center",
stopEvent: false,
offset: [0, -20],
});
this.openMap.addOverlay(this.popup);
},
// style
.popup {
width: 200px;
background-color: white;
padding: 18px;
border-radius: 10px;
box-shadow: 0 0 15px rgb(177, 177, 177);
.info {
font-size: 14px;
text-align: left;
ul {
padding-left: 0;
}
}
}
使用 ol 的 addOverlay 方法,将弹出层添加到 map 的 Overlay 上,然后修改之前的点击事件函数
singleclick() {
// 点击
this.openMap.on("singleclick", (e) => {
// 判断是否点击在点上
let feature = this.openMap.forEachFeatureAtPixel(
e.pixel,
(feature) => feature
);
console.log(feature);
if (feature) {
this.shopPopup = true;
// 设置弹窗位置
let coordinates = feature.getGeometry().getCoordinates();
this.popup.setPosition(coordinates);
} else {
this.shopPopup = false;
}
});
},
可以看到有设置弹窗位置的代码
// 设置弹窗位置
let coordinates = feature.getGeometry().getCoordinates();
this.popup.setPosition(coordinates);
获取当前点击点的坐标,然后设置给弹窗,同时之前弹窗设置了 y 轴-30 的偏移 以防覆盖掉点位标记。
至此,咱们整个点击弹窗就实现完成了。
最后,附上完整代码,主要是 Home.vue 的修改
<template>
<div class="home">
<div id="map" class="map-home"></div>
<!-- 弹框 -->
<div ref="popup" class="popup" v-show="shopPopup">
<div class="info">
<ul>
<li>信息1:xxx</li>
<li>信息2:xxx</li>
<li>信息3:xxx</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import { Map, View, Feature, Overlay } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
import * as olProj from "ol/proj";
import { Point } from "ol/geom";
import { Style, Fill, Stroke, Circle as sCircle } from "ol/style";
export default {
name: "Home",
components: {},
data() {
return {
openMap: null,
popup: null,
shopPopup: false,
};
},
mounted() {
this.initMap();
},
methods: {
initMap() {
this.openMap = new Map({
target: "map",
layers: [
new TileLayer({
source: new XYZ({
url: "https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",
}),
}),
],
view: new View({
center: olProj.fromLonLat([108.945951, 34.465262]),
zoom: 1,
}),
controls: [],
});
this.setMarker();
this.addOverlay();
this.singleclick();
this.pointermove();
},
setMarker() {
let _style = new Style({
image: new sCircle({
radius: 10,
stroke: new Stroke({
color: "#fff",
}),
fill: new Fill({
color: "#3399CC",
}),
}),
});
let _feature = new Feature({
geometry: new Point(olProj.fromLonLat([108.945951, 34.465262])),
});
_feature.setStyle(_style);
let _marker = new VectorLayer({
source: new VectorSource({
features: [_feature],
}),
});
this.openMap.addLayer(_marker);
},
addOverlay() {
// 创建Overlay
let elPopup = this.$refs.popup;
this.popup = new Overlay({
element: elPopup,
positioning: "bottom-center",
stopEvent: false,
offset: [0, -20],
});
this.openMap.addOverlay(this.popup);
},
singleclick() {
// 点击
this.openMap.on("singleclick", (e) => {
// 判断是否点击在点上
let feature = this.openMap.forEachFeatureAtPixel(
e.pixel,
(feature) => feature
);
console.log(feature);
if (feature) {
this.shopPopup = true;
// 设置弹窗位置
let coordinates = feature.getGeometry().getCoordinates();
this.popup.setPosition(coordinates);
} else {
this.shopPopup = false;
}
});
},
pointermove() {
this.openMap.on("pointermove", (e) => {
if (this.openMap.hasFeatureAtPixel(e.pixel)) {
this.openMap.getViewport().style.cursor = "pointer";
} else {
this.openMap.getViewport().style.cursor = "inherit";
}
});
},
},
};
</script>
<style lang="scss" scoped>
.map-home {
width: 100vw;
height: 100vh;
}
.popup {
width: 200px;
background-color: white;
padding: 18px;
border-radius: 10px;
box-shadow: 0 0 15px rgb(177, 177, 177);
.info {
font-size: 14px;
text-align: left;
ul {
padding-left: 0;
}
}
}
</style>
本文主要是 OpenLayers 的入门教程,完成 OpenLayers 的地图导入渲染,以及坐标点的点击事件。
感谢大家阅读
如果能帮助到您,那更是我的万分荣幸。
后面应该会陆续的更新更多的功能使用,以及项目中遇到的一些问题,感兴趣的小伙伴可以点个收藏/关注。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。