# 七.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">&copy; MapTiler</a> ' +
        '<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; 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.图像滤镜

查看代码详情
<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">&copy; MapTiler</a> ' +
      '<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; 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

# 3.KML 数据加载

查看代码详情
<template>
  <div>
    <div ref="map" class="map"></div>
    <div id="info">&nbsp;</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">&copy; MapTiler</a> ' +
      '<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; 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 = "&nbsp;";
        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

# 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">&copy; MapTiler</a> ' +
      '<a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; 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

# 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

# 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

# 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

# 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

# 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