Newer
Older
KaiFengPC / src / views / gisMapPage / gisMapBox1.vue
@zhangdeliang zhangdeliang on 23 May 17 KB 初始化项目
<template>
  <div class="mapPage">
    <div id="mapboxContainer"></div>
  </div>
</template>
<script>
import { reactive, toRefs, onBeforeMount, onMounted, nextTick, onBeforeUnmount } from 'vue';
import bus from '@/bus';
import axios from 'axios';
import xiaoganWater from '@/assets/geojson/xiaoganWater.json';
import xiaoganWaterLabel1 from '@/assets/geojson/xiaoganWaterLabel1.json';
import xiaoganWaterLabel2 from '@/assets/geojson/xiaoganWaterLabel2.json';
import xiaoganWaterLabel3 from '@/assets/geojson/xiaoganWaterLabel3.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.href.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);
          console.log('spritesspritessprites', sprites);

          !!!map.getSource('xiaoganWater') && map.addSource('xiaoganWater', { type: 'geojson', data: xiaoganWater });
          !!!map.getLayer('xiaoganWater') &&
            map.addLayer({
              id: 'xiaoganWater',
              type: 'fill',
              source: 'xiaoganWater',
              paint: {
                'fill-color': '#0c3b7a',
              },
            });
          addWaterLabel();
          await loadData();
          // map.on('styleimagemissing', e => {
          //   console.log('styleimagemissing', e);
          //   (sprites || []).forEach(url => {
          //     map.style._loadSprite(url.includes('http') ? url : window.location.href.split('#')[0] + url);
          //   });
          //   let pointLayput = config.mapbox.filter(item => item.id == 'point');
          //   console.log('pointLayput', pointLayput[0]['layout']['icon-image']);
          //   setTimeout(() => {
          //     map.setLayoutProperty('point', 'icon-image', pointLayput[0]['layout']['icon-image']);
          //   }, 1000);
          // });

          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);
          }, 2000);
          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))[0];
        if (feature) event.emit('map-click', Object.values(e.lngLat), feature.properties);
        setHighlight(feature);
      });
    };

    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: 14,
                  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 => {
          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.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;
          })
      );

      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 addWaterLabel = () => {
      !!!map.getSource('xiaoganWaterLabel1') && map.addSource('xiaoganWaterLabel1', { type: 'geojson', data: xiaoganWaterLabel1 });
      !!!map.getLayer('xiaoganWaterLabel1') &&
        map.addLayer({
          id: 'xiaoganWaterLabel1',
          type: 'symbol',
          source: 'xiaoganWaterLabel1',
          layout: {
            'text-field': ['get', 'name'],
            'text-font': ['KlokanTech Noto Sans Regular'],
            'text-transform': 'uppercase',
          },
          paint: {
            'text-halo-color': 'rgba(0,0,0,1)',
            'text-color': 'rgba(0,167,210,1)',
            'icon-opacity': 1,
            'text-halo-width': 1,
          },
        });
      !!!map.getSource('xiaoganWaterLabel2') && map.addSource('xiaoganWaterLabel2', { type: 'geojson', data: xiaoganWaterLabel2 });
      !!!map.getLayer('xiaoganWaterLabel2') &&
        map.addLayer({
          id: 'xiaoganWaterLabel2',
          type: 'symbol',
          source: 'xiaoganWaterLabel2',
          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(0,0,0,1)',
            'text-color': 'rgba(0,167,210,1)',
            'icon-opacity': 1,
            'text-halo-width': 1,
          },
        });
      !!!map.getSource('xiaoganWaterLabel3') && map.addSource('xiaoganWaterLabel3', { type: 'geojson', data: xiaoganWaterLabel3 });
      !!!map.getLayer('xiaoganWaterLabel3') &&
        map.addLayer({
          id: 'xiaoganWaterLabel3',
          type: 'symbol',
          source: 'xiaoganWaterLabel3',
          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(0,0,0,1)',
            'text-color': 'rgba(0,167,210,1)',
            'icon-opacity': 1,
            'text-halo-width': 1,
          },
        });
    };
    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;
  }
  .l7-control-mouse-location {
    color: #ffffff;
  }
}
</style>