Newer
Older
KaiFengPC / src / views / gisMapPage / gisMapBox1.vue
@jimengfei jimengfei 19 days ago 18 KB updata
<template>
  <div class="mapPage">
    <div id="mapboxContainer"></div>
  </div>
</template>
<script>
import bus from '@/bus';
import axios from 'axios';
import kaifengWaterLabel1 from '@/assets/geojson/kaifeng/kaifengWaterLabel1.json';
import kaifengWater from '@/assets/geojson/kaifeng/kaifengWater.json';
import kaifengAllBoundary from '@/assets/geojson/kaifeng/kaifengAllBoundary.json';
import kaiFengCenteralBoundary from '@/assets/geojson/kaifeng/kaiFengCenteralBoundary.json';
import riverFlow from '@/assets/geojson/kaifeng/riverFlow.json';

export default {
  components: {},
  props: {
    initJson: {
      type: String,
      default: () => '/static/libs/mapbox/style/floodOneMap.json',
    },
    loadCallback: {
      type: Function,
      default: () => function () {},
    },
  },
  setup(props, event) {
    const allData = reactive({
      layerIds: [],
    });
    let geojson = {
      point: { type: 'FeatureCollection', features: [] },
      polygon: { type: 'FeatureCollection', features: [] },
      linestring: { type: 'FeatureCollection', features: [] },
    };
    let map = null;
    let config = null;
    let highlightLayers = {
      highlight_point: 1,
      //highlight_point1: 1,
      highlight_polygon: 1,
      highlight_linestring: 1,
    };
    const initeMap = async () => {
      config = (await axios.get(props.initJson)).data;
      let { sprites, l7 } = config.params;

      window.newfiberMapbox = new mapboxL7.Scene({
        id: 'mapboxContainer',
        map: new mapboxL7.Mapbox({
          style: config.params.init.style,
          center: config.params.init.center,
          zoom: config.params.init.zoom,
        }),
      });
      newfiberMapbox.map.load = false;
      map = newfiberMapbox.map;
      map.ogcLayers = [];
      newfiberMapbox.unLoadLayers = [];
      (sprites || []).forEach(url => map.style._loadSprite(url.includes('http') ? url : window.location.origin.split('#')[0] + url));
      ((l7 || []).images || []).forEach(item =>
        newfiberMapbox.addImage(item.name, item.url.includes('http') ? item.url : window.location.href.split('#')[0] + item.url)
      );
      setTimeout(() => {
        map.on('load', async () => {
          const mouseLocation = new mapboxL7.MouseLocation({
            transform: position => {
              return [position[0].toFixed(6), position[1].toFixed(6)];
            },
          });
          newfiberMapbox.addControl(mouseLocation);
          // !!!map.getSource('kaifengWater') && map.addSource('kaifengWater', { type: 'geojson', data: kaifengWater });
          // !!!map.getLayer('kaifengWater') &&
          //   map.addLayer({
          //     id: 'kaifengWater',
          //     type: 'fill',
          //     source: 'kaifengWater',
          //     paint: {
          //       'fill-color': 'rgba(117, 207, 240,1)',
          //     },
          //   });
          //addRiverFlow();
          addWaterLabel();
          //addAreaBoundary();
          await loadData();

          props.loadCallback && props.loadCallback();
          // getLayerIdByClick();
          (config.orders || []).forEach(item => setLayerOrder(...item));
          newfiberMapbox.getLayers().filter(i => highlightLayers[i.newfiberId] && (highlightLayers[i.newfiberId] = i));
          // let timeout = setTimeout(() => {
          let { pitch, center } = config.params.init;
          pitch && newfiberMapbox.map.setPitch(pitch);
          center && newfiberMapbox.map.setCenter(center);
          //clearTimeout(timeout);
          //}, 1000);
          newfiberMapbox.map.load = true;
        });
      }, 200);

      let layerIds = (config.mapbox || []).map(i => i.id);
      map.on('click', e => {
        Object.values(highlightLayers).forEach(layer => {
          if (layer.setData) layer.setData({ type: 'FeatureCollection', features: [] });
        });
        const feature = (
          map.queryRenderedFeatures([
            [e.point.x - 10 / 2, e.point.y - 10 / 2],
            [e.point.x + 10 / 2, e.point.y + 10 / 2],
          ]) || []
        ).filter(i => layerIds.includes(i.layer.id) || i.layer.id == 'rainStation')[0];
        if (feature) event.emit('map-click', Object.values(e.lngLat), feature.properties);
        setHighlight(feature);
      });
      map.on('mouseenter', 'point', e => {
        Object.values(highlightLayers).forEach(layer => {
          if (layer.setData) layer.setData({ type: 'FeatureCollection', features: [] });
        });
        const feature = (
          map.queryRenderedFeatures([
            [e.point.x - 10 / 2, e.point.y - 10 / 2],
            [e.point.x + 10 / 2, e.point.y + 10 / 2],
          ]) || []
        ).filter(i => layerIds.includes(i.layer.id))[0];
        if (feature) event.emit('map-moveOn', Object.values(e.lngLat), feature.properties);
        setHighlight(feature);
      });
      map.on('mouseleave', 'point', e => {
        Object.values(highlightLayers).forEach(layer => {
          if (layer.setData) layer.setData({ type: 'FeatureCollection', features: [] });
        });
        const feature = (
          map.queryRenderedFeatures([
            [e.point.x - 10 / 2, e.point.y - 10 / 2],
            [e.point.x + 10 / 2, e.point.y + 10 / 2],
          ]) || []
        ).filter(i => layerIds.includes(i.layer.id))[0];
        if (feature) event.emit('map-moveLeave', Object.values(e.lngLat), feature.properties);
      });
    };

    const loadData = async () => {
      let { mapbox, l7, ogc } = config;
      if (mapbox)
        //用mapbox添加水系
        //axios.get(config.params.mvt + `/v1/geojson/hubei_xiaogan_water1`).then(({ data: geojson }) => {

        // });
        mapbox.forEach(item => {
          let { mType, columns } = item;
          let params = '';
          if (columns) params = `?columns=${columns}`;
          if (!!!map.getSource(item.id)) {
            let flag = mType == 'geojson';
            flag
              ? map.addSource(item.id, {
                  type: mType,
                  data: geojson[item.id],
                })
              : map.addSource(item.id, {
                  type: 'vector',
                  tiles: [config.params.mvt + `/v1/${mType}/${item.key}/{z}/{x}/{y}` + params],
                  tileSize: 512,
                  scheme: 'xyz',
                  maxzoom: 24,
                  minzoom: 1,
                });
          }
          map.addLayer({ ...item, source: item.id });
          map.moveLayer(item.id, undefined);
          allData.layerIds.push(item.id);
        });
      if (l7) {
        if (!!!l7.length) return;
        l7.forEach(item => {
          let { id, columns, filter } = item;
          let params = '';
          if (columns) params += `columns=${columns}&`;
          if (filter) params += `filter=${filter}&`;
          id
            ? axios.get(config.params.mvt + `/v1/geojson/${id}?` + params).then(({ data: geojson }) => initMapBoxL7Class(item, geojson))
            : initMapBoxL7Class(item, geojson[item.key] || turf.featureCollection([]));
        });
      }
      if (ogc)
        ogc.forEach(item => {
          let { id, type, params, methods } = item;
          Object.keys(params).forEach(
            i => (params[i] = typeof params[i] == 'string' ? (params[i].includes('||') ? eval(params[i]) : params[i]) : params[i])
          );
          let layer = new mapboxgl1[type](params);
          layer.newfiberId = id;
          methods.forEach(method => {
            let ms = method.params.map(i => (typeof i == 'string' ? (i.includes('||') ? eval(i) : i) : i));
            layer[method.name](...ms);
          });
          map.ogcLayers.push(layer);
        });

      function initMapBoxL7Class({ type, params, methods, id, show, key }, geojson) {
        let layer = new mapboxL7[type](params).source(geojson);
        methods.forEach(method => {
          let ms = method.params.map(i => (typeof i == 'string' ? (i.includes('||') ? eval(i) : i) : i));
          layer[method.name](...ms);
        });
        layer.newfiberId = key;
        if (!show) return newfiberMapbox.unLoadLayers.push(layer);
        newfiberMapbox.addLayer(layer);
        allData.layerIds.push(key);
      }
    };

    const setLayerVisible = ({ layername, isCheck }) => {
      if (!!!window.newfiberMapbox) return;
      if (((config || {}).filter || {})[layername]) {
        config.filter[layername].layerName.forEach((name, index) => {
          let filter = map.getFilter(name);
          let fValues = config.filter[layername].filter[index];
          isCheck ? filter.push(...fValues) : (filter = filter.filter(i => !fValues.includes(i)));
          map.setFilter(name, filter);
        });
        return config.filter[layername].easeTo && isCheck && map.easeTo(config.filter[layername].easeTo);
      }
      let features = Object.values(geojson)
        .map(i => i.features)
        .flat(Infinity)
        .filter(i => i.properties.type == layername);
      if (features.length) {
        let types = Array.from(new Set(features.map(i => i.geometry.type.toLocaleLowerCase())));
        types.forEach(type1 => {
          if (map.getLayer(type1)) {
            let filter = map.getFilter(type1);
            if (!!!filter) return;
            isCheck ? filter.push(layername) : (filter = filter.filter(i => i != layername));

            map.setFilter(type1, filter);
          }
        });
      }
      let layer = newfiberMapbox.getLayers().filter(i => i.newfiberId == layername)[0];
      if (!!!layer) {
        layer = newfiberMapbox.unLoadLayers.filter(i => i.newfiberId == layername)[0];
        isCheck && layer && newfiberMapbox.addLayer(layer);
      }
      layer && layer[['hide', 'show'][Number(isCheck)]]();

      layer = map.getLayer(layername);
      layer && map.setLayoutProperty(layername, 'visibility', isCheck ? 'visible' : 'none');

      layer = map.getLayer(layername + '_text');
      layer && map.setLayoutProperty(layername, 'visibility', isCheck ? 'visible' : 'none');

      layer = map.ogcLayers.filter(i => i.id == layername)[0];
      layer && (layer.map ? layer[isCheck ? 'show' : 'hide']() : layer.addTo(map));
    };

    const getGeojsonByType = ({ type, callback }) => {
      let geojs = turf.featureCollection(
        Object.values(geojson)
          .map(i => i.features)
          .flat(Infinity)
          .filter(i => i.properties.type == type)
      );
      callback && callback(geojs);
    };

    const removeLayers = ids => {
      let { getLayers, removeAllLayer, removeLayer: removeLayerL7 } = newfiberMapbox;
      let { getLayer, removeLayer } = map;

      if (!!!ids) {
        allData.layerIds.forEach(id => getLayer(id) && removeLayer(id));
        return removeAllLayer();
      }

      ids.forEach(id => {
        getLayer(id) && removeLayer(id);
        getLayers().forEach(layer => layer.newfiberId == id && removeLayerL7(layer));
      });
    };

    const removeMapDatas = types => {
      !!!types
        ? Object.keys(geojson).forEach(key => (geojson[key].features.length = 0))
        : Object.keys(geojson).forEach(
            key => (geojson[key].features = geojson[key].features.filter(feature => !types.includes(feature.properties.type)))
          );
      return refreshGeoJSON();
    };

    const setLegendData = list => {
      list.forEach(i => {
        i.data &&
          i.data.features &&
          i.data.features.forEach(a => {
            if (!!!a || !!!a.properties) return;
            a.properties.type = a.properties.type || i.layername;
            a.properties.name =
              a.properties.name ||
              a.properties.Name ||
              a.properties.stName ||
              a.properties.roadName ||
              a.properties.sewageName ||
              a.properties.sectionName ||
              a.properties.pumpName ||
              a.properties.projectName ||
              a.properties.plantName;
          });
      });

      let types = {};
      list
        .map(i => i.data && i.data.features)
        .filter(Boolean)
        .flat(Infinity)
        .forEach(feature => {
          if (!!!feature || !!!feature.properties) return;
          feature.properties.geometry = Terraformer.WKT.convert(feature.geometry);
          let type = feature.geometry.type.toLocaleLowerCase();
          let flag = type.includes('multi');
          type = type.replaceAll('multi', '');
          let features = null;
          if (flag) features = turf.flatten(feature).features;
          !!!types[type] && (types[type] = []);
          types[type].push(...(features ? features : [feature]));
        });
      Object.keys(types).forEach(key => geojson[key].features.push(...types[key]));
      refreshGeoJSON();
    };

    const refreshGeoJSON = () => {
      Object.keys(geojson).forEach(key => map.getSource(key) && map.getSource(key).setData(geojson[key]));
    };

    const setGeoJSON = ({ json, key }) => {
      // geojson[key] = json;
      let layer = newfiberMapbox.getLayers().filter(i => i.newfiberId == key)[0];
      if (!!!layer) {
        layer = newfiberMapbox.unLoadLayers.filter(i => i.newfiberId == key)[0];
        layer && newfiberMapbox.addLayer(layer);
      }
      if (layer) layer.setData(json);
      setLegendData([{ data: json, layername: key, type: 'point' }]);
    };

    const setLayerOrder = (sourceLayer, targetLayer) => {
      map.moveLayer(sourceLayer, targetLayer);
    };

    const setHighlight = (features = {}) => {
      let array = {};
      features = features.forEach ? features : [features];
      Object.values(highlightLayers).forEach(layer => layer.setData && layer.setData({ type: 'FeatureCollection', features: [] }));
      features.forEach(feature => {
        if (!!!feature || !Boolean(Object.keys(feature).length) || !feature.properties.geometry) return;
        let geometry = Terraformer.WKT.parse(feature.properties.geometry);
        let geoFeature = turf.feature(geometry, feature.properties);
        let type = geometry.type.toLocaleLowerCase().replaceAll('multi', '');
        let key = Object.keys(highlightLayers).filter(key => key.lastIndexOf(type) > -1)[0];
        if (!array[key]) array[key] = [];
        array[key].push(geoFeature);
      });
      Object.keys(array).forEach(
        key => highlightLayers[key] && highlightLayers[key].setData({ type: 'FeatureCollection', features: array[key] })
      );
    };

    const getLayerIdByClick = () => {
      map.getStyle().layers.forEach(i =>
        map.on('click', i.id, (a, b, c, d) => {
          console.log('layer-id', a.features[0].layer.id);
        })
      );
    };

    //添加政区边界
    const addAreaBoundary = () => {
      !!!map.getSource('kaifengAllBoundary') && map.addSource('kaifengAllBoundary', { type: 'geojson', data: kaifengAllBoundary });
      !!!map.getLayer('kaifengAllBoundary') &&
        map.addLayer({
          id: 'kaifengAllBoundary',
          type: 'line',
          source: 'kaifengAllBoundary',

          paint: {
            'line-color': 'rgba(255,208,76,1)',
            'line-width': 6,
          },
        });
      !!!map.getSource('kaiFengCenteralBoundary') &&
        map.addSource('kaiFengCenteralBoundary', { type: 'geojson', data: kaiFengCenteralBoundary });
      !!!map.getLayer('kaiFengCenteralBoundary') &&
        map.addLayer({
          id: 'kaiFengCenteralBoundary',
          type: 'line',
          source: 'kaiFengCenteralBoundary',

          paint: {
            'line-color': 'rgba(228,64,50,1)',
            'line-width': 6,
          },
        });
    };
    //添加河流标注
    const addWaterLabel = () => {
      !!!map.getSource('kaifengWaterLabel1') && map.addSource('kaifengWaterLabel1', { type: 'geojson', data: kaifengWaterLabel1 });
      !!!map.getLayer('kaifengWaterLabel1') &&
        map.addLayer({
          id: 'kaifengWaterLabel1',
          type: 'symbol',
          source: 'kaifengWaterLabel1',
          layout: {
            'text-field': ['get', 'name'],
            'text-font': ['KlokanTech Noto Sans Regular'],
            'text-transform': 'uppercase',
            'text-size': 12,
          },
          paint: {
            'text-halo-color': 'rgba(238, 251, 255,1)',
            'text-color': 'rgba(30, 30, 30,1)',
            'icon-opacity': 1,
            'text-halo-width': 1,
          },
        });
      !!!map.getSource('kaifengWaterLabel2') && map.addSource('kaifengWaterLabel2', { type: 'geojson', data: kaifengWater });
      !!!map.getLayer('kaifengWaterLabel2') &&
        map.addLayer({
          id: 'kaifengWaterLabel2',
          type: 'symbol',
          source: 'kaifengWaterLabel2',
          layout: {
            'symbol-placement': 'line',
            'text-field': ['get', 'name'],
            'text-font': ['KlokanTech Noto Sans Regular'],
            'text-letter-spacing': 0.1,
            'text-rotation-alignment': 'map',
            'text-size': {
              base: 1.4,
              stops: [
                [10, 16],
                [20, 22],
              ],
            },
            'text-transform': 'uppercase',
          },
          paint: {
            'text-halo-color': 'rgba(238, 251, 255,1)',
            'text-color': 'rgba(30, 30, 30,1)',
            'icon-opacity': 1,
            'text-halo-width': 1,
          },
        });
    };
    //添加河道流向
    const addRiverFlow = () => {
      let layer = new mapboxL7.LineLayer({})
        .source(riverFlow)
        .size(6)
        .shape('line')
        .texture('arrow')
        .color('rgb(117, 207, 240)')
        .animate({
          interval: 1, // 间隔
          duration: 1.5, // 持续时间,延时
          trailLength: 2, // 流线长度
        })
        .style({
          opacity: 0.6,
          lineTexture: true, // 开启线的贴图功能
          iconStep: 200, // 设置贴图纹理的间距
          borderWidth: 0.4, // 默认文 0,最大有效值为 0.5
          borderColor: '#fff', // 默认为 #ccc
        });
      newfiberMapbox.addLayer(layer);
    };
    onMounted(() => {
      initeMap();
      bus.on('setLayerVisible', setLayerVisible);
      bus.on('setLegendData', setLegendData);
      bus.on('setGeoJSON', setGeoJSON);
      bus.on('getGeojsonByType', getGeojsonByType);
      bus.on('removeLayers', removeLayers);
      bus.on('removeMapDatas', removeMapDatas);
      bus.on('setHighlight', setHighlight);
    });

    onBeforeUnmount(() => {
      bus.off('setLayerVisible');
      bus.off('setLegendData');
      bus.off('setGeoJSON');
      bus.off('getGeojsonByType');
      bus.off('removeMapDatas');
      bus.off('setHighlight');
      newfiberMapbox.destroy();
      newfiberMapbox = null;
    });

    return {
      ...toRefs(allData),
      initeMap,
    };
  },
};
</script>
<style lang="scss">
.mapPage {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0px;
  top: 0px;
  z-index: 10;
  background: lavender;
  #mapboxContainer {
    width: 100%;
    height: 100%;
    position: absolute;
  }
  .l7-control-mouse-location {
    background: none;
  }
}
</style>