# openlayers
# 概述
openlayers一个高性能、功能丰富的JavaScript库,可以在网页中展示动态地图,是一款免费开源的JavaScript库。
# 主要类
# Map类
Map是Openlayers的核心类,对于要渲染的地图,需要一个视图、一个或多个图层以及一个目标容器。
# View类
View对象表示地图的2D视图
# Layer类
ol/layer/Tile (瓦片图层)
ol/layer/Image (图片图层)
ol/layer/Vector (矢量图层)
ol/layer/VectorTile (矢量瓦片图层)
ol/layer/WebGLTile(webgl瓦片图层)
Layer类的数据来源是Source类,不同类型的Layer加载不同类型的Source
# Source类
- Tile sources for ol/layer/Tile or ol/layer/WebGLTile
- Image sources for ol/layer/Image
- Vector sources for ol/layer/Vector
- Vector tile sources for ol/layer/VectorTile
<template>
<div class="vm">
<h2 class="h-title">加载天地图底图</h2>
<div id="map" class="map-x"></div>
</div>
</template>
<script>
import 'ol/ol.css'
import { Map, View } from 'ol'
import Tile from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
export default {
name: 'FirstMap',
data () {
return {
map: null
}
},
methods: {
initMap () {
// 地图实例
this.map = new Map({
target: "map", // 对应页面里 id 为 map 的dom元素
layers: [ // 图层
new Tile({
source: new XYZ({ //天地图矢量底图
url: 'http://t0.tianditu.com/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk=4d314458b2e0a90a498c0ae62142c9fd',
projection: "EPSG:4326",
}),
}),
new Tile({
source: new XYZ({
url: 'http://t6.tianditu.com/DataServer?T=cva_c&x={x}&y={y}&l={z}&tk=4d314458b2e0a90a498c0ae62142c9fd',
})
}),
],
view: new View({ // 地图视图
projection: "EPSG:4326", // 坐标系,有EPSG:4326和EPSG:3857
center: [110.064839, 32.548857], // 中心点坐标
// minZoom:10, // 地图缩放最小级别
zoom: 5 // 地图缩放级别(打开页面时默认级别)
})
})
},
},
mounted () {
this.initMap();
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 要素操作
# 判断指定图层是否存在
isLayerExist(layerName) {
let flag = false;
this.map.getLayers().forEach((element) => {
if (element && element.get('name') == layerName) {
flag = true;
}
});
return flag;
},
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 根据图层名称移除指定图层
removeLayerByName(layerName) {
this.map.getLayers().forEach((element) => {
if (element && element.get('name') == layerName) {
this.$nextTick(() => {
this.map.removeLayer(element);
});
}
});
},
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 添加图层要素点击选中事件
import { Select } from "ol/interaction";
export function addLayerClick(clickLayer) {
let selectClick = new Select({
condition: singleClick,
style: null,//取消默认选中样式
// style: areaStyles,
filter: (feature, layer) => {
return layer === clickLayer; // 需要添加事件的layer
}
});
return selectClick;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 展示点位
import VectorSource from "ol/source/Vector";
import { Feature } from "ol";
import { Point } from "ol/geom";
import Vector from "ol/layer/Vector";
import { Style, Icon } from "ol/style";
showPoints(coordinates, styleObj, layerName = 'pointLayer'){
if (this.isLayerExist(layerName)) this.removeLayerByName(layerName);
//构建数据源
let vectorSource = new VectorSource({});
coordinates.forEach(element => {
let point = [element.lng, element.lat];
const iconFeature = new Feature({
geometry: new Point(point),
data: element
});
vectorSource.addFeature(iconFeature);
});
//构建点位图层
let vectorLayer = new Vector({
name:layerName,
source: vectorSource,
zIndex: 10,
style: feature => {
const featureData = feature.getProperties().data;
let style = new Style({
image: new Icon({
anchor: styleObj.anchor || [0.5, 0.5],
anchorXUnits: styleObj.anchorXUnits || "fraction",
anchorYUnits: styleObj.anchorYUnits || "fraction",
src: featureData.src || styleObj.src, //点位图标从这边取
scale: styleObj.scale || 1,
rotation: featureData.rotation || 0
}),
});
return style;
}
});
//把图层添加到地图对象上
this.map.addLayer(vectorLayer);
let selectClick = addLayerClick(pointLayer);
selectClick.on('select', (e) => {
let features = e.target.getFeatures().getArray();
//获取到选中要素信息进行操作
});
this.map.addInteraction(selectClick);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 展示聚合点位
import VectorSource from "ol/source/Vector";
import { Feature } from "ol";
import { Point } from "ol/geom";
import Vector from "ol/layer/Vector";
import { Style, Icon, Fill, Icon, Text } from "ol/style";
import Cluster from "ol/source/Cluster";
import { boundingExtent } from 'ol/extent';
/**
* 画聚合点位并将图层点位绑定事件
* @param {Array} coordinate 点位列表
* @param {Object} styleObj 样式对象
* @param {String} layerName 点位图层名称
*/
showClusterPoint(coordinates, styleObj, layerName = 'pointLayer') {
if (this.isLayerExist(layerName)) this.removeLayerByName(layerName);
const features = coordinates
.filter(item => item.lng && item.lat)
.map(point => {
return new Feature({
geometry: new Point([point.lng, point.lat]),
data: point
});
});
//聚合源
const clusterSource = new Cluster(
{
distance: styleObj.distance || 20,
source: new VectorSource({ features })
}
);
/**
* 计算聚合点位样式
*/
const computedClusterStyle = feature => {
const size = feature.get("features").length;
let textOption = { font: "normal 12px 微软雅黑", padding: [1, 2, 1, 2] };
const featureData = feature.getProperties().features[0].values_.data;
if (size == 1) {
let titleData = `${featureData.name}`;
textOption = {
...textOption,
fill: new Fill({ color: "#333" }),
backgroundFill: new Fill({ color: "#fff" }),
text: titleData,
offsetY: styleObj.textOffsetY || -36 //调整标题显示位置
};
} else if (size > 1) {
textOption = {
...textOption,
text: `${size}`,
fill: new Fill({ color: "#fff" }),
backgroundFill: new Fill({ color: "#fff0" }),
offsetX: styleObj.textOffsetX || 15,
offsetY: styleObj.textOffsetY || -10
};
}
const titleText = new Text(textOption);
return new Style({
image: new Icon({
radius: 10,
anchor: styleObj.anchor || [0.5, 0.5],
anchorXUnits: styleObj.anchorXUnits || "fraction",
anchorYUnits: styleObj.anchorYUnits || "fraction",
src: size == 1 ? featureData.src || styleObj.src : featureData.srcs || styleObj.srcs || "",//根据点位数量判断图标
scale: styleObj.scale || 1
}),
text: titleText
});
}
const pointLayer = new Vector({
name: layerName,
source: clusterSource,
zIndex: 10,
style: computedClusterStyle
});
this.map.addLayer(pointLayer);
let selectClick = addLayerClick(pointLayer);
selectClick.on('select', (e) => {
let features = e.target.getFeatures().getArray()[0].values_.features;
//点击层级放大 点位散开
if (features.length > 1) {
const extent = boundingExtent(features.map((r) => r.getGeometry().getCoordinates()));
this.map.getView().fit(extent, { duration: 1000, padding: [100, 100, 100, 100] });
}
if (features.length == 1) {
//执行获取到点位数据后的具体操作
//this.$emit('point-click', features[0].values_.data);
}
});
this.map.addInteraction(selectClick);
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 展示线要素
showLine(arr,layerName) {
if (this.isLayerExist(layerName)) this.removeLayerByName(layerName);
let vectorSource = new VectorSource({});
arr.forEach(element => {
const lineFeature = new Feature({
geometry: new LineString(element.coordinates),
data: element
});
const lineStyle = new Style({
fill: new Fill({
color: element.fillColor || "rgba(255, 255, 255, 1)"
}),
stroke: new Stroke({
color: element.lineColor || "#00C1FF",
width: element.lineWidth || 2,
lineDash: [10, 10]
}),
text: new Text({
text: element.text, // 路线标签文字
font: "normal 12px 微软雅黑", //字体样式
fill: new Fill({
//文字填充样式
color: element.fontColor || [16, 168, 218, 1]
}),
backgroundFill: new Fill({
color: [255, 255, 255, 0]
}),
padding: [1, 2, 1, 2]
})
});
lineFeature.setStyle(lineStyle);
vectorSource.addFeature(lineFeature);
});
let vectorLayer = new Vector({
name:layerName,
source: vectorSource,
zIndex: 10
});
this.map.addLayer(vectorLayer);
const selectClick = addLayerClick(tempLayer);
selectClick.on('select', (e) => {
let features = e.target.getFeatures().getArray();
//获取到选中要素信息进行操作
});
this.map.addInteraction(selectClick);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
← CSS架构方案 Vue2源码-core →