# 六.Layer(二)
# 1.高级地图框矢量图
响应速度与交互性是矢量地图的优点,一旦从服务器获得了矢量数据,Web 地图用户与数据的交互就会非常迅速,不会有任何延迟。另外,矢量图形无论进行放大、缩小或旋转等操作,图形都不会失真。
矢量地图的缺点是不能同时绘制成百上千个要素,因为矢量地图的主要操作都在客户端,所以数据量变大,客户端就会卡、慢,甚至可能崩溃
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
format: { MVT },
Map,
tilegrid: { TileGrid },
View,
layer: { VectorTile: VectorTileLayer },
source: { VectorTile: VectorTileSource },
style: { Fill, Icon, Stroke, Style, Text },
proj: { get: getProjection },
} = ol
const resolutions = []
for (let i = 0; i <= 8; ++i) {
resolutions.push(156543.03392804097 / Math.pow(2, i * 2))
}
function tileUrlFunction(tileCoord) {
return (
"https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/" +
"{z}/{x}/{y}.vector.pbf?access_token=" +
mapkeys.mapbox
)
.replace("{z}", String(tileCoord[0] * 2 - 1))
.replace("{x}", String(tileCoord[1]))
.replace("{y}", String(tileCoord[2]))
.replace(
"{a-d}",
"abcd".substr(((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1)
)
}
new Map({
layers: [
new VectorTileLayer({
source: new VectorTileSource({
attributions:
'© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
'© <a href="https://www.openstreetmap.org/copyright">' +
"OpenStreetMap contributors</a>",
format: new MVT(),
tileGrid: new TileGrid({
extent: getProjection("EPSG:3857").getExtent(),
resolutions: resolutions,
tileSize: 512,
}),
tileUrlFunction: tileUrlFunction,
}),
}),
],
target: this.$refs.map,
view: new View({
center: [12579156, 3274244],
minZoom: 1,
zoom: 2,
}),
})
},
}
</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
53
54
55
56
57
58
59
60
61
62
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
# 2.其他属性
属性 | 作用 | 说明 |
---|---|---|
className | 要设置为图层元素的 CSS 类名 | |
opacity | 设置地图的不透明度,值的范围为:0-1 | |
zIndex | 图层渲染的 z 索引。在渲染时,图层将被排序,首先按 Z 索引排序,然后按位置排序。当 undefined,对于添加到地图图 layers 集合的图层,假设 zIndex0,或者当使用图层的 setMap()方法时,假设为 Infinity |
# 1.className
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { WebGLTile: TileLayer },
source: { OSM },
} = ol
new Map({
target: this.$refs.map,
layers: [
new TileLayer({
source: new OSM(),
className: "layer-style", // 要设置为图层元素的 CSS 类名
opacity: 0.5, // 设置地图的不透明度
zIndex: 0, // 地图层级
}),
],
view: new View({
center: [12579156, 3274244],
zoom: 12,
}),
})
},
}
</script>
<style>
.layer-style {
width: 50% !important;
}
</style>
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
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
# 2.LayerGroup
查看代码详情
<template>
<div>
<div ref="map" class="map"></div>
<div id="layertree">
<h5>单击下面的层节点以更改其属性</h5>
<ul>
<li>
<span>OSM 图层</span>
<fieldset id="layer0">
<label class="checkbox" for="visible0">
visible <input id="visible0" class="visible" type="checkbox" />
</label>
<label>
opacity
<input class="opacity" type="range" min="0" max="1" step="0.01" />
</label>
</fieldset>
</li>
<li>
<span>图层组</span>
<fieldset id="layer1">
<label class="checkbox" for="visible1">
visible <input id="visible1" class="visible" type="checkbox" />
</label>
<label>
opacity
<input class="opacity" type="range" min="0" max="1" step="0.01" />
</label>
</fieldset>
<ul>
<li>
<span>粮食不安全图层</span>
<fieldset id="layer10">
<label class="checkbox" for="visible10">
visible
<input id="visible10" class="visible" type="checkbox" />
</label>
<label>
opacity
<input
class="opacity"
type="range"
min="0"
max="1"
step="0.01"
/>
</label>
</fieldset>
</li>
<li>
<span>世界边界图层</span>
<fieldset id="layer11">
<label class="checkbox" for="visible11">
visible
<input id="visible11" class="visible" type="checkbox" />
</label>
<label>
opacity
<input
class="opacity"
type="range"
min="0"
max="1"
step="0.01"
/>
</label>
</fieldset>
</li>
</ul>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer, Group: LayerGroup },
source: { OSM, TileJSON },
proj: { fromLonLat },
} = ol;
const map = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
new LayerGroup({
layers: [
new TileLayer({
source: new TileJSON({
url:
"https://api.tiles.mapbox.com/v4/mapbox.20110804-hoa-foodinsecurity-3month.json?secure&access_token=" +
mapkeys.mapbox,
crossOrigin: "anonymous",
}),
}),
new TileLayer({
source: new TileJSON({
url:
"https://api.tiles.mapbox.com/v4/mapbox.world-borders-light.json?secure&access_token=" +
mapkeys.mapbox,
crossOrigin: "anonymous",
}),
}),
],
}),
],
target: this.$refs.map,
view: new View({
center: fromLonLat([37.4057, 8.81566]),
zoom: 4,
}),
});
function bindInputs(layerid, layer) {
const visibilityInput = $(layerid + " input.visible");
visibilityInput.on("change", function () {
layer.setVisible(this.checked);
});
visibilityInput.prop("checked", layer.getVisible());
const opacityInput = $(layerid + " input.opacity");
opacityInput.on("input change", function () {
layer.setOpacity(parseFloat(this.value));
});
opacityInput.val(String(layer.getOpacity()));
}
function setup(id, group) {
group.getLayers().forEach(function (layer, i) {
const layerid = id + i;
bindInputs(layerid, layer);
if (layer instanceof LayerGroup) {
setup(layerid, layer);
}
});
}
setup("#layer", map.getLayerGroup());
$("#layertree li > span")
.click(function () {
$(this).siblings("fieldset").toggle();
})
.siblings("fieldset")
.hide();
},
};
</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
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# 3.分层裁剪
postrender
prerender
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer },
source: { OSM },
} = ol
const osm = new TileLayer({
source: new OSM(),
})
const map = new Map({
layers: [osm],
target: this.$refs.map,
view: new View({
center: [12579156, 3274244],
zoom: 2,
}),
})
osm.on("prerender", function (event) {
const ctx = event.context
const matrix = event.inversePixelTransform
const canvasPixelRatio = Math.sqrt(
matrix[0] * matrix[0] + matrix[1] * matrix[1]
)
const canvasRotation = -Math.atan2(matrix[1], matrix[0])
ctx.save()
ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2)
ctx.rotate(-canvasRotation)
ctx.scale(3 * canvasPixelRatio, 3 * canvasPixelRatio)
ctx.translate(-75, -80)
ctx.beginPath()
ctx.moveTo(75, 40)
ctx.bezierCurveTo(75, 37, 70, 25, 50, 25)
ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5)
ctx.bezierCurveTo(20, 80, 40, 102, 75, 120)
ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5)
ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25)
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40)
ctx.clip()
ctx.translate(75, 80)
ctx.scale(1 / 3 / canvasPixelRatio, 1 / 3 / canvasPixelRatio)
ctx.rotate(canvasRotation)
ctx.translate(-ctx.canvas.width / 2, -ctx.canvas.height / 2)
})
osm.on("postrender", function (event) {
const ctx = event.context
ctx.restore()
})
},
}
</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
53
54
55
56
57
58
59
60
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
# 4.setOpacity
修改图层不透明度
查看代码详情
<template>
<div>
<div ref="map" class="map"></div>
<label>
图层透明度
<input
ref="opacityinput"
type="range"
min="0"
max="1"
step="0.01"
value="1"
/>
<span ref="opacityoutput"></span>
</label>
</div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { WebGLTile: TileLayer },
source: { XYZ, OSM },
style: Style,
proj: { fromLonLat },
} = ol;
const imagery = new TileLayer({
className: "ol-layer-imagery",
source: new XYZ({
attributions:
'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> ',
url:
"https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=" +
mapkeys.maptiler,
maxZoom: 20,
crossOrigin: "",
}),
});
const osm = new TileLayer({
source: new OSM(),
});
const map = new Map({
layers: [imagery, osm],
target: this.$refs.map,
view: new View({
center: [12579156, 3274244],
zoom: 2,
}),
});
const opacityInput = this.$refs.opacityinput;
const opacityOutput = this.$refs.opacityoutput;
function update() {
const opacity = parseFloat(opacityInput.value);
osm.setOpacity(opacity);
opacityOutput.innerText = opacity.toFixed(2);
}
opacityInput.addEventListener("input", update);
opacityInput.addEventListener("change", update);
update();
},
};
</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
53
54
55
56
57
58
59
60
61
62
63
64
65
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
# 5.瓦片图过渡
查看代码详情
<template>
<div>
<div ref="map" class="map"></div>
<label>
使用透明度过渡渲染
<input ref="transition" type="checkbox" checked />
</label>
</div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer },
source: { XYZ },
} = ol;
const attributions =
'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> ' +
'<a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>';
const url =
"https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=" +
mapkeys.maptiler;
const withTransition = new TileLayer({
source: new XYZ({ url: url, tileSize: 512, attributions: attributions }),
});
const withoutTransition = new TileLayer({
source: new XYZ({
url: url,
transition: 0,
tileSize: 512,
attributions: attributions,
}),
visible: false,
});
const map = new Map({
layers: [withTransition, withoutTransition],
target: this.$refs.map,
view: new View({
center: [12579156, 3274244],
zoom: 2,
maxZoom: 11,
}),
});
this.$refs.transition.addEventListener("change", function (event) {
const transition = event.target.checked;
withTransition.setVisible(transition);
withoutTransition.setVisible(!transition);
});
},
};
</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
53
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
← 五.Layer(一) 七.source →