# 七.XYZ
# 1.瓦片图
限制缩放级别 9 和 13 之间
查看代码详情
<template>
<div ref="map" class="map"></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 map = new Map({
target: this.$refs.map,
layers: [
new TileLayer({
source: new XYZ({
attributions: attributions,
url:
"https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=" +
mapkeys.maptiler,
}),
}),
],
view: new View({
center: [-13553864, 5918250],
zoom: 11,
minZoom: 9,
maxZoom: 13,
}),
});
},
};
</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
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
# 2.图像滤镜
查看代码详情
<template>
<div>
<div ref="map" class="map"></div>
<select id="kernel" name="kernel">
<option>none</option>
<option selected>sharpen</option>
<option value="sharpenless">sharpen less</option>
<option>blur</option>
<option>shadow</option>
<option>emboss</option>
<option value="edge">edge detect</option>
</select>
</div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer },
source: { XYZ },
proj: { fromLonLat },
} = 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 imagery = new TileLayer({
source: new XYZ({
attributions: attributions,
url:
"https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=" +
mapkeys.maptiler,
maxZoom: 20,
crossOrigin: "",
}),
});
const map = new Map({
layers: [imagery],
target: this.$refs.map,
view: new View({
center: fromLonLat([-120, 50]),
zoom: 6,
}),
});
const kernels = {
none: [0, 0, 0, 0, 1, 0, 0, 0, 0],
sharpen: [0, -1, 0, -1, 5, -1, 0, -1, 0],
sharpenless: [0, -1, 0, -1, 10, -1, 0, -1, 0],
blur: [1, 1, 1, 1, 1, 1, 1, 1, 1],
shadow: [1, 2, 1, 0, 1, 0, -1, -2, -1],
emboss: [-2, 1, 0, -1, 1, 1, 0, 1, 2],
edge: [0, 1, 0, 1, -4, 1, 0, 1, 0],
};
function normalize(kernel) {
const len = kernel.length;
const normal = new Array(len);
let i,
sum = 0;
for (i = 0; i < len; ++i) {
sum += kernel[i];
}
if (sum <= 0) {
normal.normalized = false;
sum = 1;
} else {
normal.normalized = true;
}
for (i = 0; i < len; ++i) {
normal[i] = kernel[i] / sum;
}
return normal;
}
const select = document.getElementById("kernel");
let selectedKernel = normalize(kernels[select.value]);
select.onchange = function () {
selectedKernel = normalize(kernels[select.value]);
map.render();
};
imagery.on("postrender", function (event) {
convolve(event.context, selectedKernel);
});
function convolve(context, kernel) {
const canvas = context.canvas;
const width = canvas.width;
const height = canvas.height;
const size = Math.sqrt(kernel.length);
const half = Math.floor(size / 2);
const inputData = context.getImageData(0, 0, width, height).data;
const output = context.createImageData(width, height);
const outputData = output.data;
for (let pixelY = 0; pixelY < height; ++pixelY) {
const pixelsAbove = pixelY * width;
for (let pixelX = 0; pixelX < width; ++pixelX) {
let r = 0,
g = 0,
b = 0,
a = 0;
for (let kernelY = 0; kernelY < size; ++kernelY) {
for (let kernelX = 0; kernelX < size; ++kernelX) {
const weight = kernel[kernelY * size + kernelX];
const neighborY = Math.min(
height - 1,
Math.max(0, pixelY + kernelY - half)
);
const neighborX = Math.min(
width - 1,
Math.max(0, pixelX + kernelX - half)
);
const inputIndex = (neighborY * width + neighborX) * 4;
r += inputData[inputIndex] * weight;
g += inputData[inputIndex + 1] * weight;
b += inputData[inputIndex + 2] * weight;
a += inputData[inputIndex + 3] * weight;
}
}
const outputIndex = (pixelsAbove + pixelX) * 4;
outputData[outputIndex] = r;
outputData[outputIndex + 1] = g;
outputData[outputIndex + 2] = b;
outputData[outputIndex + 3] = kernel.normalized ? a : 255;
}
}
context.putImageData(output, 0, 0);
}
},
};
</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
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
# 3.KML 数据加载
查看代码详情
<template>
<div>
<div ref="map" class="map"></div>
<div id="info"> </div>
</div>
</template>
<script>
export default {
mounted() {
let {
format: { KML },
Map,
View,
layer: { Tile: TileLayer, Vector: VectorLayer },
source: { XYZ, Vector: VectorSource },
} = 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 raster = new TileLayer({
source: new XYZ({
attributions: attributions,
url:
"https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=" +
mapkeys.maptiler,
maxZoom: 20,
}),
});
const vector = new VectorLayer({
source: new VectorSource({
url: this.$withBase("/data/kml/2012-02-10.kml"),
format: new KML(),
}),
});
const map = new Map({
layers: [raster, vector],
target: this.$refs.map,
view: new View({
center: [876970.8463461736, 5859807.853963373],
projection: "EPSG:3857",
zoom: 10,
}),
});
const displayFeatureInfo = function (pixel) {
const features = [];
map.forEachFeatureAtPixel(pixel, function (feature) {
features.push(feature);
});
if (features.length > 0) {
const info = [];
let i, ii;
for (i = 0, ii = features.length; i < ii; ++i) {
info.push(features[i].get("name"));
}
document.getElementById("info").innerHTML =
info.join(", ") || "(unknown)";
map.getTarget().style.cursor = "pointer";
} else {
document.getElementById("info").innerHTML = " ";
map.getTarget().style.cursor = "";
}
};
map.on("pointermove", function (evt) {
if (evt.dragging) {
return;
}
const pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});
map.on("click", function (evt) {
displayFeatureInfo(evt.pixel);
});
},
};
</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
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
# 4.插值
查看代码详情
<template>
<div>
<h4>Not Interpolated</h4>
<div id="map1" class="map"></div>
<div>
<label>
Elevation
<span id="info1">0.0</span> meters
</label>
</div>
<h4>Interpolated</h4>
<div id="map2" class="map"></div>
<div>
<label>
Elevation
<span id="info2">0.0</span> meters
</label>
</div>
</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 notInterpolated = new TileLayer({
source: new XYZ({
attributions: attributions,
url:
"https://api.maptiler.com/tiles/terrain-rgb/{z}/{x}/{y}.png?key=" +
mapkeys.maptiler,
tileSize: 512,
maxZoom: 12,
crossOrigin: "",
interpolate: false,
}),
});
const interpolated = new TileLayer({
source: new XYZ({
attributions: attributions,
url:
"https://api.maptiler.com/tiles/terrain-rgb/{z}/{x}/{y}.png?key=" +
mapkeys.maptiler,
tileSize: 512,
maxZoom: 12,
crossOrigin: "",
}),
});
const view = new View({
center: [6.893, 45.8295],
zoom: 16,
projection: "EPSG:4326",
});
const map1 = new Map({
target: "map1",
layers: [notInterpolated],
view: view,
});
const map2 = new Map({
target: "map2",
layers: [interpolated],
view: view,
});
function getHeight(rgba) {
return -10000 + (rgba[0] * 256 * 256 + rgba[1] * 256 + rgba[2]) * 0.1;
}
const info1 = document.getElementById("info1");
const info2 = document.getElementById("info2");
const showElevations = function (evt) {
if (evt.dragging) {
return;
}
const notInterpolatedPixel = notInterpolated.getData(evt.pixel);
info1.innerText = notInterpolatedPixel
? getHeight(notInterpolatedPixel).toFixed(1)
: "-";
const interpolatedPixel = interpolated.getData(evt.pixel);
info2.innerText = interpolatedPixel
? getHeight(interpolatedPixel).toFixed(1)
: "-";
};
map1.on("pointermove", showElevations);
map2.on("pointermove", showElevations);
},
};
</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
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
# 5.Mapbox-gl 层
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
format: { GeoJSON },
Map,
View,
layer: { Heatmap: HeatmapLayer, Layer },
source: { Source, Vector: VectorSource },
proj: { fromLonLat, toLonLat },
} = ol
const center = [-98.8, 37.9]
const mbMap = new mapboxgl.Map({
style:
"https://api.maptiler.com/maps/bright/style.json?key=" +
mapkeys.maptiler,
attributionControl: false,
boxZoom: false,
center: center,
container: "map",
doubleClickZoom: false,
dragPan: false,
dragRotate: false,
interactive: false,
keyboard: false,
pitchWithRotate: false,
scrollZoom: false,
touchZoomRotate: false,
})
const mbLayer = new Layer({
render: function (frameState) {
const canvas = mbMap.getCanvas()
const viewState = frameState.viewState
const visible = mbLayer.getVisible()
canvas.style.display = visible ? "block" : "none"
canvas.style.position = "absolute"
const opacity = mbLayer.getOpacity()
canvas.style.opacity = opacity
const rotation = viewState.rotation
mbMap.jumpTo({
center: toLonLat(viewState.center),
zoom: viewState.zoom - 1,
bearing: (-rotation * 180) / Math.PI,
animate: false,
})
if (mbMap._frame) {
mbMap._frame.cancel()
mbMap._frame = null
}
mbMap._render()
return canvas
},
source: new Source({
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 cities = new HeatmapLayer({
source: new VectorSource({
url: this.$withBase("/data/geojson/world-cities.geojson"),
format: new GeoJSON(),
}),
weight: function (feature) {
return feature.get("population") / 1e7
},
radius: 15,
blur: 15,
})
const map = new Map({
target: this.$refs.map,
view: new View({
center: fromLonLat(center),
zoom: 4,
}),
layers: [mbLayer, cities],
})
},
}
</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
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
# 6.阴影浮雕(使用 WebGL)
查看代码详情
<template>
<div>
<div ref="map" class="map"></div>
<table class="controls">
<tr>
<td><label for="vert">vertical exaggeration:</label></td>
<td><input ref="vert" type="range" min="1" max="5" value="1" /></td>
<td><span ref="vertOut"></span> x</td>
</tr>
<tr>
<td><label for="sunEl">sun elevation:</label></td>
<td><input ref="sunEl" type="range" min="0" max="90" value="45" /></td>
<td><span ref="sunElOut"></span> °</td>
</tr>
<tr>
<td><label for="sunAz">sun azimuth:</label></td>
<td><input ref="sunAz" type="range" min="0" max="360" value="45" /></td>
<td><span ref="sunAzOut"></span> °</td>
</tr>
</table>
</div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { WebGLTile: TileLayer },
source: { OSM, XYZ },
} = ol;
const variables = {};
function elevation(xOffset, yOffset) {
return [
"+",
["*", 256, ["band", 1, xOffset, yOffset]],
[
"+",
["*", 2 * 256, ["band", 2, xOffset, yOffset]],
["*", 3 * 256, ["band", 3, xOffset, yOffset]],
],
];
}
const dp = ["*", 2, ["resolution"]];
const z0x = ["*", ["var", "vert"], elevation(-1, 0)];
const z1x = ["*", ["var", "vert"], elevation(1, 0)];
const dzdx = ["/", ["-", z1x, z0x], dp];
const z0y = ["*", ["var", "vert"], elevation(0, -1)];
const z1y = ["*", ["var", "vert"], elevation(0, 1)];
const dzdy = ["/", ["-", z1y, z0y], dp];
const slope = ["atan", ["^", ["+", ["^", dzdx, 2], ["^", dzdy, 2]], 0.5]];
const aspect = ["clamp", ["atan", ["-", 0, dzdx], dzdy], -Math.PI, Math.PI];
const sunEl = ["*", Math.PI / 180, ["var", "sunEl"]];
const sunAz = ["*", Math.PI / 180, ["var", "sunAz"]];
const cosIncidence = [
"+",
["*", ["sin", sunEl], ["cos", slope]],
[
"*",
["*", ["cos", sunEl], ["sin", slope]],
["cos", ["-", sunAz, aspect]],
],
];
const scaled = ["*", 255, cosIncidence];
const shadedRelief = new TileLayer({
opacity: 0.3,
source: new XYZ({
url: "https://{a-d}.tiles.mapbox.com/v3/aj.sf-dem/{z}/{x}/{y}.png",
}),
style: {
variables: variables,
color: ["color", scaled, scaled, scaled],
},
});
const controlIds = ["vert", "sunEl", "sunAz"];
controlIds.forEach(
function (id) {
const control = this.$refs[id];
const output = this.$refs[id + "Out"];
function updateValues() {
output.innerText = control.value;
variables[id] = Number(control.value);
}
updateValues();
const listener = function () {
updateValues();
shadedRelief.updateStyleVariables(variables);
};
control.addEventListener("input", listener);
control.addEventListener("change", listener);
}.bind(this)
);
const map = new Map({
target: this.$refs.map,
layers: [
new TileLayer({
source: new OSM(),
}),
shadedRelief,
],
view: new View({
extent: [-13675026, 4439648, -13580856, 4580292],
center: [-13615645, 4497969],
minZoom: 10,
maxZoom: 16,
zoom: 13,
}),
});
},
};
</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
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
# 7.XYZ
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer },
source: { XYZ },
} = ol
const map = new Map({
target: this.$refs.map,
layers: [
new TileLayer({
source: new XYZ({
url:
"https://{a-c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png" +
"?apikey=Your API key from https://www.thunderforest.com/docs/apikeys/ here",
}),
}),
],
view: new View({
center: [-472202, 7530279],
zoom: 12,
}),
})
},
}
</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
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
# 8.瓦片大小设置
图层 | layer | source | 备注 |
---|---|---|---|
layer1 | Tile | XYZ | "https://services.arcgisonline.com/arcgis/rest/services/" +"ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}" |
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer },
source: { XYZ },
} = ol
new Map({
target: this.$refs.map,
layers: [
new TileLayer({
source: new XYZ({
attributions: "Copyright:© 2013 ESRI, i-cubed, GeoEye",
url:
"https://services.arcgisonline.com/arcgis/rest/services/" +
"ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}",
maxZoom: 15,
projection: "EPSG:4326",
tileSize: 512,
maxResolution: 180 / 512,
wrapX: true,
}),
}),
],
view: new View({
center: [12579156, 3274244],
projection: "EPSG:4326",
zoom: 2,
minZoom: 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
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
# 9.arcgison
图层 | layer | source | 备注 |
---|---|---|---|
layer1 | Tile | XYZ | "https://server.arcgisonline.com/ArcGIS/rest/services/" +"World_Topo_Map/MapServer/tile/{z}/{y}/{x}" |
查看代码详情
<template>
<div ref="map" class="map"></div>
</template>
<script>
export default {
mounted() {
let {
Map,
View,
layer: { Tile: TileLayer },
source: { XYZ },
proj: { fromLonLat },
} = ol
const map = new Map({
target: this.$refs.map,
layers: [
new TileLayer({
source: new XYZ({
attributions:
'Tiles © <a href="https://services.arcgisonline.com/ArcGIS/' +
'rest/services/World_Topo_Map/MapServer">ArcGIS</a>',
url:
"https://server.arcgisonline.com/ArcGIS/rest/services/" +
"World_Topo_Map/MapServer/tile/{z}/{y}/{x}",
}),
}),
],
view: new View({
center: fromLonLat([-121.1, 47.5]),
zoom: 7,
}),
})
},
}
</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
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
← 六.WMTS 八.VectorTile →