Newer
Older
urbanLifeline_YanAn / public / static / libs / mapbox / RainsLayer.js
@jimengfei jimengfei on 14 Oct 5 KB updata
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined'
    ? (module.exports = factory())
    : typeof define === 'function' && define.amd
    ? define(factory)
    : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), (global.mapboxgl1.RainsLayer = factory()));
})(window, function () {
  async function urlToFile(url, fileName) {
    // 使用 fetch 获取图片并转换为 Blob
    const response = await fetch(url);
    const blob = await response.blob();
    // 将 Blob 转换为 File 对象
    const file = new File([blob], fileName, { type: blob.type });
    return file;
  }
  const createCanvas = id => {
    let canvas = document.createElement('canvas');
    canvas.id = 'canvas' + id;
    canvas.style.display = 'none';
    document.body.append(canvas);
    return canvas;
  };
  const createPlot = async (e, canvas, scaleKey, plot) => {
    var tif = await GeoTIFF.fromArrayBuffer(e.target.result);
    var tifImg = await tif.getImage();
    var readRasters = await tifImg.readRasters();
    plot == null &&
      (plot = new plotty.plot({
        canvas,
        data: readRasters[0],
        width: tifImg.getWidth(),
        height: tifImg.getHeight(),
        domain: [0, 256],
        colorScale: scaleKey,
      }));
    plot.setData(readRasters[0], tifImg.getWidth(), tifImg.getHeight());
    plot.render();
  };
  const createCanvasLayer = (canvasId, i, bbox, map) => {
    bbox = [
      [bbox[0], bbox[3]],
      [bbox[2], bbox[3]],
      [bbox[2], bbox[1]],
      [bbox[0], bbox[1]],
    ];
    if (map.getLayer('canvas-layer' + i)) {
      map.removeLayer('canvas-layer' + i);
      map.removeSource('canvas-source' + i);
    }
    map.addSource('canvas-source' + i, { type: 'canvas', canvas: canvasId, coordinates: bbox, animate: true });
    map.addLayer({ id: 'canvas-layer' + i, type: 'raster', source: 'canvas-source' + i });
    map.moveLayer('canvas-layer' + i);
  };
  const plotInit = (name, colorScale = colorScale) => {
    const minVal = colorScale[0].value;
    const maxVal = colorScale[colorScale.length - 1].value;
    let color = colorScale.filter(i => Number(i.value) / maxVal <= 1);
    if (color[color.length - 1].value / maxVal < 1) color.push({ value: maxVal, color: colorScale[color.length].color });
    plotty.addColorScale(
      name,
      color.map(i => i.color),
      color.map(i => (i.value / maxVal).toFixed(5))
    );
  };

  const setRainImage = (file, canvas, scaleKey, plot) => {
    var reader = new FileReader();
    reader.onload = e => createPlot(e, canvas, scaleKey, plot);
    reader.readAsArrayBuffer(file);
  };

  return class RainsLayer {
    map = null;
    index = null;
    bbox = null;
    callback = null;
    images = [];
    imagesFiles = [];
    canvas = null;
    plot = null;
    scales = {
      1: [
        { value: '0', color: 'rgba(7, 213, 118, 0)' },
        { value: '0.2', color: 'rgba(7, 213, 118, 1)' },
        { value: '5', color: 'rgba(38, 129, 240,1)' },
        { value: '25', color: 'rgba(255, 26, 26, 1)' },
        { value: '250', color: 'rgba(255, 26, 26, 1)' },
      ],
      3: [
        { value: '0', color: 'rgba(7, 213, 118, 0)' },
        { value: '0.2', color: 'rgba(7, 213, 118, 1)' },
        { value: '5', color: 'rgba(38, 129, 240,1)' },
        { value: '25', color: 'rgba(255, 26, 26, 1)' },
        { value: '250', color: 'rgba(255, 26, 26, 1)' },
      ],
      12: [
        { value: '0', color: 'rgba(7, 213, 118, 0)' },
        { value: '0.2', color: 'rgba(7, 213, 118, 1)' },
        { value: '5', color: 'rgba(38, 129, 240,1)' },
        { value: '25', color: 'rgba(255, 26, 26, 1)' },
        { value: '250', color: 'rgba(255, 26, 26, 1)' },
      ],
      24: [
        { value: '0', color: 'rgba(7, 213, 118, 0)' },
        { value: '0.2', color: 'rgba(7, 213, 118, 1)' },
        { value: '5', color: 'rgba(38, 129, 240,1)' },
        { value: '25', color: 'rgba(255, 26, 26, 1)' },
        { value: '250', color: 'rgba(255, 26, 26, 1)' },
      ],
    };
    constructor(bbox, images, callback) {
      this.callback = callback;
      this.bbox = bbox;
      this.images = images;
      this.init();
    }

    async init() {
      if (this.bbox.length && this.images.length) {
        Object.keys(this.scales).forEach(key => plotInit(key, this.scales[key]));
        this.canvas = createCanvas(0);
        this.imagesFiles = await Promise.all(this.images.map(url => urlToFile(url, _.last(_.split(url, '/')))));
        this.callback && this.callback(this);
      }
    }

    addTo(map) {
      this.destroy();
      this.map = map;
      createCanvasLayer(this.canvas.id, 0, this.bbox, map);
      return this;
    }

    next(scaleKey = 1) {
      if (!this.index) this.index = 0;
      this.index++;
      if (this.index >= this.images.length) this.index = 0;
      setRainImage(this.imagesFiles[this.index], this.canvas, scaleKey, this.plot);
    }

    prev(scaleKey = 1) {
      if (!this.index) this.index = 0;
      this.index++;
      if (this.index <= 0) this.index = this.imagesFiles.length;
      setRainImage(this.imagesFiles[this.index - 1], this.canvas, scaleKey, this.plot);
    }

    hide(newfiberMap) {
      newfiberMap.map.setLayoutProperty('canvas-layer0', 'visibility', 'none');
    }

    show(newfiberMap) {
      newfiberMap.map.setLayoutProperty('canvas-layer0', 'visibility', 'visible');
    }

    destroy() {
      if (this.map && this.map.getLayer('canvas-layer0')) this.map.removeLayer('canvas-layer0');
      if (this.map && this.map.getSource('canvas-source0')) this.map.removeSource('canvas-source0');
    }
  };
});