# 十.DataTile

# 1.数据瓦片

查看代码详情
<template>
    <div ref="map" class="map"></div>
  </template>
  
  <script>
  export default {
    mounted() {
      let {
        Map,
        View,
        layer: { WebGLTile: TileLayer },
        source: { DataTile },
      } = ol
      const size = 256
      const canvas = document.createElement("canvas")
      canvas.width = size
      canvas.height = size
      const context = canvas.getContext("2d")
      context.strokeStyle = "white"
      context.textAlign = "center"
      context.font = "24px sans-serif"
      const lineHeight = 30
      const map = new Map({
        target: this.$refs.map,
        layers: [
          new TileLayer({
            source: new DataTile({
              loader: function (z, x, y) {
                const half = size / 2
                context.clearRect(0, 0, size, size)
                context.fillStyle = "rgba(100, 100, 100, 0.5)"
                context.fillRect(0, 0, size, size)
                context.fillStyle = "black"
                context.fillText(`z: ${z}`, half, half - lineHeight)
                context.fillText(`x: ${x}`, half, half)
                context.fillText(`y: ${y}`, half, half + lineHeight)
                context.strokeRect(0, 0, size, size)
                const data = context.getImageData(0, 0, size, size).data
                return new Uint8Array(data.buffer)
              },
              transition: 0,
            }),
          }),
        ],
        view: new View({
          center: [12579156, 3274244],
          zoom: 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

# 2.渲染 16 位 NumpyTiles

查看代码详情
<template>
  <div>
    <div ref="map" class="map"></div>
    <div>
      <h5>对比度拉伸</h5>
      <ul>
        <li>
          Min <input type="range" min="1000" max="10000" ref="inputmin" />
          <span ref="outputmin"></span>
        </li>
        <li>
          Max <input type="range" min="10000" max="50000" ref="inputmax" />
          <span ref="outputmax"></span>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  async mounted() {
    let {
      Map,
      View,
      layer: { WebGLTile: TileLayer },
      source: { DataTile: DataTileSource },
      proj: { fromLonLat },
    } = ol;
    const COG =
      "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif";

    function numpyTileLoader(z, x, y) {
      const url = `https://api.cogeo.xyz/cog/tiles/WebMercatorQuad/${z}/${x}/${y}@1x`;
      return fetch(`${url}?format=npy&url=${encodeURIComponent(COG)}`)
        .then((r) => r.arrayBuffer())
        .then((buffer) => NumpyLoader.fromArrayBuffer(buffer))
        .then((numpyData) => {
          const dataTile = new Float32Array(256 * 256 * 5);
          const bandSize = 256 * 256;
          for (let x = 0; x < 256; x++) {
            for (let y = 0; y < 256; y++) {
              const px = x + y * 256;
              dataTile[px * 5 + 0] = numpyData.data[y * 256 + x];
              dataTile[px * 5 + 1] = numpyData.data[bandSize + y * 256 + x];
              dataTile[px * 5 + 2] = numpyData.data[bandSize * 2 + y * 256 + x];
              dataTile[px * 5 + 3] = numpyData.data[bandSize * 3 + y * 256 + x];
              dataTile[px * 5 + 4] =
                numpyData.data[bandSize * 4 + y * 256 + x] > 0 ? 1.0 : 0;
            }
          }
          return dataTile;
        });
    }

    const interpolateBand = (bandIdx) => [
      "interpolate",
      ["linear"],
      ["band", bandIdx],
      ["var", "bMin"],
      0,
      ["var", "bMax"],
      1,
    ];
    const initialMin = 3000;
    const initialMax = 18000;
    const numpyLayer = new TileLayer({
      style: {
        color: [
          "array",
          interpolateBand(3),
          interpolateBand(2),
          interpolateBand(1),
          ["band", 5],
        ],
        variables: {
          bMin: initialMin,
          bMax: initialMax,
        },
      },
      source: new DataTileSource({
        loader: numpyTileLoader,
        bandCount: 5,
      }),
    });
    const map = new Map({
      target: this.$refs.map,
      layers: [numpyLayer],
      view: new View({
        center: fromLonLat([172.933, 1.3567]),
        zoom: 15,
      }),
    });
    const inputMin = this.$refs.inputmin;
    const inputMax = this.$refs.inputmax;
    const outputMin = this.$refs.outputmin;
    const outputMax = this.$refs.outputmax;
    const handleMin = (evt) => {
      numpyLayer.updateStyleVariables({
        bMin: parseFloat(evt.target.value),
        bMax: parseFloat(inputMax.value),
      });
      outputMin.innerText = evt.target.value;
    };
    inputMin.addEventListener("input", handleMin);
    inputMin.addEventListener("change", handleMin);
    const handleMax = (evt) => {
      numpyLayer.updateStyleVariables({
        bMin: parseFloat(inputMin.value),
        bMax: parseFloat(evt.target.value),
      });
      outputMax.innerText = evt.target.value;
    };
    inputMax.addEventListener("input", handleMax);
    inputMax.addEventListener("change", handleMax);
    inputMin.value = initialMin;
    inputMax.value = initialMax;
    outputMin.innerText = initialMin;
    outputMax.innerText = initialMax;
  },
};
</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