新建vue项目
命令行输入 vue create projectName
安装openlayers
npm i ol
初始化vue项目
为了偷懒,vue项目新建成功后我直接在App.vue中使用openlayers了,在assets新建init.css初始化页面距,在同级目录components创建OlMap.vue文件,App.vue引入OlMap。
// init.css
html,
body {
margin: 0;
padding: 0;
}
// main.js
import Vue from "vue";
import App from "./App.vue";
import "./assets/css/init.css";
Vue.config.productionTip = false;
new Vue({
render: (h) => h(App),
}).$mount("#app");
// App.vue
<template>
<div class="map_wrapper">
<OlMap />
</div>
</template>
<script>
import OlMap from "./components/OlMap.vue";
export default {
name: "root",
components: {
OlMap,
},
};
</script>
<style >
/* 写demo时,偷懒在这初始化页边距,不新建init.css也可以 */
/* html,
body {
margin: 0;
padding: 0;
} */
</style>
<style lang="scss" scoped>
.map_wrapper {
height: 100vh;
}
</style>
openlayers初始化地图
创建容器,引入必要的资源,调用initMap方法初始化地图
<template>
<div class="wrapper" id="map"></div>
</template>
<script>
import { Map, View } from "ol";
// 图层
import { Vector, Tile } from "ol/layer";
// openLayers自带的数据源
import OSM from "ol/source/OSM";
// 其他地图的数据源
import XYZ from "ol/source/XYZ";
import "ol/ol.css";
export default {
name: "olMap",
data() {
return {
// 缩放层级
zoom: 16,
// 定位中心点
center: {
lon: 113.27,
lat: 23.13,
},
};
},
mounted() {
this.initMap();
},
methods: {
initMap() {
let tileOSM = new Tile({
// ol自带的数据源
source: new OSM(),
// 如果要引入其他地图的数据源,通过XYZ引入
// source: new XYZ({
// url: "http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=你的密钥,",
// }),
});
let view = new View({
zoom: this.zoom,
center: [this.center.lon, this.center.lat],
//坐标系
projection: "EPSG:4326",
});
// 建议将map实例放在全局变量中,如果放在data中,数据量太大会造成ol卡死
window.map = new Map({
layers: [tileOSM],
view,
target: "map",
});
},
},
};
</script>
<style lang="scss" scoped>
.wrapper {
height: 100%;
}
// 去除右下角水印
::v-deep .ol-attribution {
display: none;
}
// 去除左上角控制栏
::v-deep .ol-control {
display: none;
}
</style>
地图初始化后就可以在页面中看到效果,接下来,我们用openlayers绘制简单的点线面。
openlayers绘制点线面
openlayer绘制图形,需要经历如下几个步骤,获取矢量要素,将矢量要素添加到几何图形(Feature)中,将feature添加到VectorSource,再将VectorSource添加到矢量图层(Vector)中,最近将Vector添加到map实例即可。
了解openlayers绘制流程后,就可以开始绘制图形了,先在OlMap引入绘图需要的一些类。
// 图形
import { Point, LineString, Polygon, Circle } from "ol/geom";
// 样式
import { Style, Icon, Fill, Stroke } from "ol/style";
import { format } from "ol/coordinate";
import MousePosition from "ol/control/MousePosition.js";
// 几何图形类
import Feature from "ol/Feature";
import VectorSource from "ol/source/Vector";
绘制点:在methdos中创建createPoint的方法,
createPoint(coordinates) {
let styleList = [
new Style({
image: new Icon({
anchorXUnits: "pixels",
anchorYUnits: "pixels",
src: require("../assets/images/position.png"),
scale: 0.2,
}),
}),
];
let point = new Point(coordinates);
let feature = new Feature(point);
let vectorSource = new VectorSource({
features: [feature],
});
let vector = new Vector({
source: vectorSource,
style: function (feature) {
return styleList;
},
});
/** 给矢量图层添加style有两种方式,一种是给style属性赋值一个方法,在方法中将style返回,
返回时style必须是一个数组,另外一种就是直接给style属性赋值对象,第一种方式可以同时添加多个
Style的实例对象,只需要将它们都放在同一个数组中即可,而第二种方式只能添加一个Style的实例对象。
let vector = new Vector({
source: vectorSource,
style: new Style({
image: new Icon({
anchorXUnits: "pixels",
anchorYUnits: "pixels",
src: require("../assets/images/position.png"),
scale: 0.2,
}),
}),
});
*/
return vector;
},
调用CreatePoint的方法进行绘图
handlePoint(){
let point = this.createPoint([113.269356, 23.135343]);
// point拿到的是矢量图层,需要将矢量图层添加到map中。
map.addLayer(point);
}
因为所有图形的绘制流程大同小异,我们将createPoint中公共的部分抽离出来,封装成一个单独的方法,考虑到style中可能有多个Style实例对象,我使用数组的方式进行给矢量图层添加样式。
/**
* 绘制图层
* @param { Object } source 数据源
* @param { Array } style style数组
*/
createLayer(source, style) {
let feature = new Feature(source);
let vectorSource = new VectorSource({
features: [feature],
});
let vector = new Vector({
source: vectorSource,
style: function (feature) {
return style;
},
});
return vector;
},
我们对createPoint改造一下,调用方法跟上述相同。
createPoint(coordinates) {
let styleList = [
new Style({
image: new Icon({
anchorXUnits: "pixels",
anchorYUnits: "pixels",
src: require("../assets/images/position.png"),
scale: 0.2,
}),
}),
];
let point = new Point(coordinates);
return this.createLayer(point, styleList);
},
handlePoint() {
let point = this.createPoint([113.269356, 23.135343]);
map.addLayer(point);
}
到这里,我们绘制点的功能就完成了,因为有createLayer方法的存在,绘制不同的图形,只需要传不同的source跟style即可。
// 画线
createLine(coordinates) {
let line = new LineString(coordinates);
let styleList = [
new Style({
stroke: new Stroke({
color: "#f00",
width: 2,
}),
}),
];
return this.createLayer(line, styleList);
},
// 该方法最终需要到vue的生命周期钩子中调用才能看到效果
drawLine() {
let line = this.createLine([
[113.266674, 23.133626],
[113.267876, 23.130086],
]);
map.addLayer(line);
},
// 画多边形
createPolygon(coordinates) {
let polygon = new Polygon(coordinates);
let styleList = [
new Style({
stroke: new Stroke({
color: "#EE82EE",
width: 1,
}),
fill: new Fill({
color: "rgba(238,130,238, 0.25)",
}),
}),
];
return this.createLayer(polygon, styleList);
},
drawPolygon() {
// 需要注意的是,画面的数据格式是三维数组
let polygon = this.createPolygon([
[
[113.270665, 23.130365],
[113.274807, 23.131674],
[113.274485, 23.127876],
],
]);
map.addLayer(polygon);
},
至此,绘制点、线、面的功能就实现了,可能会有小伙伴点击绘图的功能需求,我们只需要监听map的click事件就可以拿到点击的经纬度坐标了,将经纬度传给创建图形的方法就可以了。
map.on("click", function (e) {
console.log(e);
/** 需要注意的是,绘制新的图形时,旧的图形并不会被删除,需要手动删除,
手动代码如下,本例子是绘制点,绘制线、面同理,都需要将以前的图形删掉
*/
if(this.point){
this.point.getSource().clear()
map.removeLayer(this.point)
}
// 画点,将point的矢量图层保存下来,
this.point = this.createPoint(e.coordinate)
map.addLayer(this.point)
});
至此,vue初步使用openlayers完成,OlMap完整代码如下:
<template>
<div class="wrapper" id="map"></div>
</template>
<script>
import { Map, View } from "ol";
// 图层
import { Vector, Tile } from "ol/layer";
// openLayers自带的数据源
import OSM from "ol/source/OSM";
// 其他地图的数据源
import XYZ from "ol/source/XYZ";
// 图形
import { Point, LineString, Polygon, Circle } from "ol/geom";
// 样式
import { Style, Icon, Fill, Stroke } from "ol/style";
import { format } from "ol/coordinate";
import MousePosition from "ol/control/MousePosition.js";
// 几何图形类
import Feature from "ol/Feature";
import VectorSource from "ol/source/Vector";
import "ol/ol.css";
export default {
name: "olMap",
data() {
return {
// 缩放层级
zoom: 16,
// 定位中心点
center: {
lon: 113.27,
lat: 23.13,
},
point: null,
};
},
mounted() {
this.initMap();
this.drawPoint();
this.drawPolygon();
this.drawLine();
map.on("click", this.clickMap);
},
methods: {
initMap() {
let tileOSM = new Tile({
// ol自带的数据源
source: new OSM(),
// 如果要引入其他地图的数据源,通过XYZ引入
// source: new XYZ({
// url: "http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=你的密钥,",
// }),
});
let view = new View({
zoom: this.zoom,
center: [this.center.lon, this.center.lat],
//坐标系
projection: "EPSG:4326",
});
// 建议将map实例放在全局变量中,如果放在data中,数据量太大会造成ol卡死
window.map = new Map({
layers: [tileOSM],
view,
target: "map",
});
},
clickMap(e) {
console.log(e);
/** 需要注意的是,绘制新的图形时,旧的图形并不会被删除,需要手动删除,
手动代码如下,本例子是绘制点,绘制线、面同理,都需要将以前的图形删掉
*/
if (this.point) {
this.point.getSource().clear();
map.removeLayer(this.point);
}
// 画点,将point的矢量图层保存下来,
this.point = this.createPoint(e.coordinate);
map.addLayer(this.point);
},
drawPoint() {
let point = this.createPoint([113.269356, 23.135343]);
map.addLayer(point);
},
drawPolygon() {
let polygon = this.createPolygon([
[
[113.270665, 23.130365],
[113.274807, 23.131674],
[113.274485, 23.127876],
],
]);
map.addLayer(polygon);
},
drawLine() {
let line = this.createLine([
[113.266674, 23.133626],
[113.267876, 23.130086],
]);
map.addLayer(line);
},
createPoint(coordinates) {
let styleList = [
new Style({
image: new Icon({
anchorXUnits: "pixels",
anchorYUnits: "pixels",
src: require("../assets/images/position.png"),
scale: 0.2,
}),
}),
];
let point = new Point(coordinates);
return this.createLayer(point, styleList);
},
createPolygon(coordinates) {
let polygon = new Polygon(coordinates);
let styleList = [
new Style({
stroke: new Stroke({
color: "#EE82EE",
width: 1,
}),
fill: new Fill({
color: "rgba(238,130,238, 0.25)",
}),
}),
];
return this.createLayer(polygon, styleList);
},
createLine(coordinates) {
let line = new LineString(coordinates);
let styleList = [
new Style({
stroke: new Stroke({
color: "#f00",
width: 2,
}),
}),
];
return this.createLayer(line, styleList);
},
/**
* 绘制图层
* @param { Object } source 数据源
* @param { Array } style style数组
*/
createLayer(source, style) {
let feature = new Feature(source);
let vectorSource = new VectorSource({
features: [feature],
});
let vector = new Vector({
source: vectorSource,
style: function (feature) {
return style;
},
});
return vector;
},
},
};
</script>
<style lang="scss" scoped>
.wrapper {
height: 100%;
}
// 去除右下角水印
::v-deep .ol-attribution {
display: none;
}
// 去除左上角控制栏
::v-deep .ol-control {
display: none;
}
</style>