前言
最近公司有需求,需要用到openlayers实现在地图上面绘制多边形,并且轨迹回放,实现弹出框,国内资料太少了,所以在这里放上openlayers的学习教程以及这个案例的代码
基础知识的准备
openlayers中文文档:点击这里去中文文档
openlayers常用的API:点击这里去API总结处
openlayers官网:官网
//提示:用Edge可以对这个英文网站进行翻译
栗子:vue+openlayers实现覆盖物+popup
效果:
<!-- -->
<template>
<div class="showOverlay">
<div id="map"></div>
<!-- 提示框 -->
<div id="popup" ref="popupRef"></div>
</div>
</template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
//引入主要组件
import { Feature, Map, Overlay, View } from "ol";
//引入layer
import ImageLayer from "ol/layer/Image";
import VectorLayer from "ol/layer/Vector";
//引入source
import Static from "ol/source/ImageStatic";
import VectorSource from "ol/source/Vector";
//其他
import Projection from "ol/proj/Projection";
import { getCenter } from "ol/extent";
import { Point } from "ol/geom";
import { Style, Icon } from "ol/style";
//import { Style, Icon, Text, Fill, Stroke } from "ol/style";
//导入图片
import mapImage from "@/assets/img/map1.jpg"; //底图
import personImg from "@/assets/img/anchor.png";
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {
map: null, //地图
// imgW: 0, //图片的宽高
// imgH: 0,
persons: [], //人员
features: [], //覆盖物
feature: null,
vectorource: new VectorSource(), //矢量数据
};
},
//计算属性 类似于data概念
computed: {},
//监控data中的数据变化
watch: {
persons(newVal) {
if (newVal) {
this.setFeature();
}
},
},
//方法集合
methods: {
//初始化地图
initMap() {
//限制范围
let extent = [0, 0, 2560, 1920];
//投影
let projection = new Projection({
//SRS 标识符代码,例如EPSG:4326
code: "xkcd-image",
// 单位。必需,除非 定义 PROJ4 投影。code
units: "pixels",
//SRS 的有效性范围。
extent: extent,
});
//layers--图片底图
let mapLayer = new ImageLayer({
source: new Static({
url: mapImage,
projection: projection,
imageExtent: extent,
}),
});
//layer--矢量图层
let featureLayer = new VectorLayer({
source: this.vectorource,
});
//创建地图
this.map = new Map({
target: "map",
layers: [mapLayer, featureLayer],
view: new View({
//配置投影
projection: projection,
//配置中心
center: getCenter(extent),
//配置zoom
zoom: 2,
//配置最大zoom
maxZoom: 10,
}),
});
//添加覆盖物
let overlay = new Overlay({
//OverLay元素
element: document.querySelector("#popup"),
//跟随平移
autoPan: true,
//偏移量--数组第一个元素为水平偏移,正右负左;数组第二个元素为垂直,正下负上;
offset: [0, 2],
//覆盖物位置
// position: [0, 0],
});
this.map.addOverlay(overlay);
//给map绑定事件
this.map.on("pointermove", this.showPopup);
},
//hover显示覆盖物
showPopup(e) {
console.log(e);
// let that = this; //vue实例
let oPopup = this.$refs.popupRef; //获取到popup元素
//获取到图层上的feature (pixel:像素,callback(f:根据像素返回的feature))
let feature = this.map.forEachFeatureAtPixel(e.pixel, (f) => f);
// console.log(feature);
if (feature) {
// console.log(feature.getProperties());
// 把对应的人的信息在popup中展示出来
// console.log("ren", this.persons);
this.persons.filter((item) => {
if (item.name == feature.getProperties().name) {
oPopup.innerHTML = `<p>姓名:${item.name}</p>`;
// 设置popup的位置
this.map.getOverlays().array_[0].setPosition(e.coordinate);
}
});
} else {
this.map.getOverlays().array_[0].setPosition(undefined);
}
},
//设置feature人
setFeature() {
// let that = this; //vue实例
// this.features = [];
// this.map.getLayers();清除掉原本矢量图上的source that.vectorSource.clear();
// this.vectorource.clear();
//添加每个feature
this.persons.map((item) => {
this.feature = new Feature({
geometry: new Point([item.x, item.y]),
name: item.name,
});
//设置feature的样式(使用锚点)
this.feature.setStyle(
new Style({
image: new Icon({
//设置icon的锚,默认是中心[0.5,0.5]
anchor: [0, 1],
//设置icon的图片
src: personImg,
}),
// text: new Text({
// // 位置
// textAlign: "center",
// // 基准线
// textBaseline: "middle",
// // 文字样式
// font: "normal 20px 微软雅黑",
// // 文本内容
// text: item.name,
// // 文本填充样式(即文字颜色)
// fill: new Fill({ color: "#aa3300" }),
// stroke: new Stroke({ color: "#ffcc33", width: 2 }),
// }),
})
);
//添加每个feature到features数组中
this.features.push(this.feature);
});
//将feature添加到矢量图层去
this.vectorource.addFeatures(this.features);
},
},
beforeCreate() {}, //生命周期 - 创建之前
//生命周期 - 创建完成(可以访问当前this实例)
created() {
//在此周期给persons添加数据
this.persons = [
{ id: 1, name: "点-1", x: 497.08, y: 187.88, z: 0 },
{ id: 2, name: "点-2", x: 725.32, y: 565.88, z: 0 },
{ id: 3, name: "点-3", x: 643.24, y: 503.96, z: 0 },
];
},
beforeMount() {}, //生命周期 - 挂载之前
//生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
//初始化地图
this.initMap();
// this.showPopup();
},
beforeUpdate() {}, //生命周期 - 更新之前
updated() {}, //生命周期 - 更新之后
beforeDestroy() {}, //生命周期 - 销毁之前
destroyed() {}, //生命周期 - 销毁完成
activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style scoped>
#map {
width: 1000px;
height: 800px;
border: 1px solid #333;
margin: 0 auto;
}
#popup {
width: 200px;
height: 80px;
padding: 0 20px;
border-radius: 5px;
z-index: 1;
opacity: 1;
position: absolute;
bottom: 0;
left: 0;
margin: 0;
background: rgba(0, 60, 136, 0.7);
color: white;
border: 0;
transition: opacity 100ms ease-in;
}
</style>