# 十八.TileJSON

# 1.UTFGrid

查看代码详情
<template>
  <div>
    <div id="map" class="map"></div>
    <div style="display: none">
      <div id="country-info">
        <div id="country-name">&nbsp;</div>
        <img id="country-flag" />
      </div>
    </div>
  </div>
</template>
  
  <script>
export default {
  mounted() {
    let {
      Overlay,
      Map,
      View,
      layer: { Tile: TileLayer },
      source: { TileJSON, UTFGrid },
    } = ol;

    const mapLayer = new TileLayer({
      source: new TileJSON({
        url:
          "https://api.tiles.mapbox.com/v4/mapbox.geography-class.json?secure&access_token=" +
          mapkeys.mapbox,
      }),
    });
    const gridSource = new UTFGrid({
      url:
        "https://api.tiles.mapbox.com/v4/mapbox.geography-class.json?secure&access_token=" +
        mapkeys.mapbox,
    });
    const gridLayer = new TileLayer({ source: gridSource });
    const view = new View({
      center: [12579156, 3274244],
      zoom: 1,
    });
    const mapElement = document.getElementById("map");
    const map = new Map({
      layers: [mapLayer, gridLayer],
      target: mapElement,
      view: view,
    });
    const infoElement = document.getElementById("country-info");
    const flagElement = document.getElementById("country-flag");
    const nameElement = document.getElementById("country-name");
    const infoOverlay = new Overlay({
      element: infoElement,
      offset: [15, 15],
      stopEvent: false,
    });
    map.addOverlay(infoOverlay);
    const displayCountryInfo = function (coordinate) {
      const viewResolution = view.getResolution();
      gridSource.forDataAtCoordinateAndResolution(
        coordinate,
        viewResolution,
        function (data) {
          mapElement.style.cursor = data ? "pointer" : "";
          if (data) {
            flagElement.src = "data:image/png;base64," + data["flag_png"];
            nameElement.innerHTML = data["admin"];
          }
          infoOverlay.setPosition(data ? coordinate : undefined);
        }
      );
    };
    map.on("pointermove", function (evt) {
      if (evt.dragging) {
        return;
      }
      const coordinate = map.getEventCoordinate(evt.originalEvent);
      displayCountryInfo(coordinate);
    });
    map.on("click", function (evt) {
      displayCountryInfo(evt.coordinate);
    });
  },
};
</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

# 2.区域增长

查看代码详情
<template>
  <div>
    <div ref="map" class="map"></div>
    <div>
      <label class="input-group">
        Threshold:
        <input id="threshold" type="range" min="1" max="50" value="20" />
        <span id="threshold-value"></span>
      </label>
    </div>
  </div>
</template>

<script>
export default {
  mounted() {
    let {
      Map,
      View,
      layer: { Tile: TileLayer, Vector: VectorLayer, Image: ImageLayer },
      source: { XYZ, Raster: RasterSource },
      proj: { fromLonLat },
    } = ol;
    function growRegion(inputs, data) {
      const image = inputs[0];
      let seed = data.pixel;
      const delta = parseInt(data.delta);
      if (!seed) {
        return image;
      }
      seed = seed.map(Math.round);
      const width = image.width;
      const height = image.height;
      const inputData = image.data;
      const outputData = new Uint8ClampedArray(inputData);
      const seedIdx = (seed[1] * width + seed[0]) * 4;
      const seedR = inputData[seedIdx];
      const seedG = inputData[seedIdx + 1];
      const seedB = inputData[seedIdx + 2];
      let edge = [seed];
      while (edge.length) {
        const newedge = [];
        for (let i = 0, ii = edge.length; i < ii; i++) {
          const next = next4Edges(edge[i]);
          for (let j = 0, jj = next.length; j < jj; j++) {
            const s = next[j][0];
            const t = next[j][1];
            if (s >= 0 && s < width && t >= 0 && t < height) {
              const ci = (t * width + s) * 4;
              const cr = inputData[ci];
              const cg = inputData[ci + 1];
              const cb = inputData[ci + 2];
              const ca = inputData[ci + 3];
              if (ca === 0) {
                continue;
              }
              if (
                Math.abs(seedR - cr) < delta &&
                Math.abs(seedG - cg) < delta &&
                Math.abs(seedB - cb) < delta
              ) {
                outputData[ci] = 255;
                outputData[ci + 1] = 0;
                outputData[ci + 2] = 0;
                outputData[ci + 3] = 255;
                newedge.push([s, t]);
              }
              inputData[ci + 3] = 0;
            }
          }
        }
        edge = newedge;
      }
      return { data: outputData, width: width, height: height };
    }
    function next4Edges(edge) {
      const x = edge[0];
      const y = edge[1];
      return [
        [x + 1, y],
        [x - 1, y],
        [x, y + 1],
        [x, y - 1],
      ];
    }
    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 raster = new RasterSource({
      sources: [imagery.getSource()],
      operationType: "image",
      operation: growRegion,
      lib: {
        next4Edges: next4Edges,
      },
    });
    const rasterImage = new ImageLayer({
      opacity: 0.7,
      source: raster,
    });
    const map = new Map({
      layers: [imagery, rasterImage],
      target: this.$refs.map,
      view: new View({
        center: fromLonLat([-119.07, 47.65]),
        zoom: 11,
      }),
    });
    let coordinate;
    map.on("click", function (event) {
      coordinate = event.coordinate;
      raster.changed();
    });
    const thresholdControl = document.getElementById("threshold");
    raster.on("beforeoperations", function (event) {
      const data = event.data;
      data.delta = thresholdControl.value;
      if (coordinate) {
        data.pixel = map.getPixelFromCoordinate(coordinate);
      }
    });
    function updateControlValue() {
      document.getElementById("threshold-value").innerText =
        thresholdControl.value;
    }
    updateControlValue();
    const listener = function () {
      updateControlValue();
      raster.changed();
    };
    thresholdControl.addEventListener("input", listener);
    thresholdControl.addEventListener("change", listener);
  },
};
</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