Newer
Older
KaiFengH5 / src / views / xuncha / gisCommonPage / newFiberMapBox.vue
@jimengfei jimengfei 22 days ago 13 KB updata
<template>
  <div class="mapPage">
    <div id="cesiumContainer"></div>
  </div>
</template>
<script setup name="OneMap">
import bus from '@/utils/utils';
import axios from 'axios';
import * as turf from '@turf/turf';
import WKT from 'terraformer-wkt-parser';
import kaifengWaterLabel1 from '@/assets/geojson/kaifengWaterLabel1.json';
import kaifengWater from '@/assets/geojson/kaifengWater.json';

const props = defineProps({
  initJson: {
    type: String,
    default: () => '/static/libs/mapbox/style/floodOneMap.json',
  },
  loadCallback: {
    type: Function,
    default: () => function () {},
  },

  PostionValue: Object,
});

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_polygon: 1,
  highlight_linestring: 1,
};
const initeMap = async () => {
  config = (await axios.get(props.initJson)).data;
  window.newfiberMap = new mapboxL7.Scene({
    id: 'cesiumContainer',
    map: new mapboxL7.Mapbox({
      style: config.params.init.style,
      center: config.params.init.center,
      zoom: config.params.init.zoom,
    }),
  });
  map = newfiberMap.map;
  map.ogcLayers = [];
  newfiberMap.unLoadLayers = [];

  map.on('load', async () => {
    // 坐标拾取器
    // const mouseLocation = new mapboxL7.MouseLocation({
    //   transform: (position) => {
    //     return position;
    //   },
    // });
    // newfiberMap.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)',
        },
      });
    addWaterLabel();
    let { sprites, l7 } = config.params;
    (sprites || []).forEach((url) =>
      map.style._loadSprite(url.includes('http') ? url : window.location.href.split('#')[0] + url)
    );
    ((l7 || []).images || []).forEach((item) =>
      newfiberMap.addImage(
        item.name,
        item.url.includes('http') ? item.url : window.location.href.split('#')[0] + item.url
      )
    );
    await loadData();
    props.loadCallback && props.loadCallback();
    //getLayerIdByClick();
    (config.orders || []).forEach((item) => setLayerOrder(...item));
    newfiberMap.getLayers().filter((i) => highlightLayers[i.newfiberId] && (highlightLayers[i.newfiberId] = i));

    let timeout = setTimeout(() => {
      let { pitch, center } = config.params.init;
      pitch && newfiberMap.map.setPitch(pitch);
      // center && newfiberMap.map.setCenter(center);
      clearTimeout(timeout);
    }, 2000);

    // three();
  });

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

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 = 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 loadData = async () => {
  let { mapbox, l7, ogc } = config;
  if (mapbox)
    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)
    l7.forEach((item) => {
      let { id, columns } = item;
      let params = '';
      if (columns) params = `?columns=${columns}`;
      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) =>
        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 newfiberMap.unLoadLayers.push(layer);
    newfiberMap.addLayer(layer);
    allData.layerIds.push(key);
  }
};

const setLayerVisible = ({ layername, isCheck }) => {
  if (!!!(config || {}).filter) 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);
      isCheck ? filter.push(layername) : (filter = filter.filter((i) => i != layername));
      map.setFilter(type1, filter);
    });
  }
  let layer = newfiberMap.getLayers().filter((i) => i.newfiberId == layername)[0];
  if (!!!layer) {
    layer = newfiberMap.unLoadLayers.filter((i) => i.newfiberId == layername)[0];
    isCheck && layer && newfiberMap.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 } = newfiberMap;
  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.pointNumber ||
          a.properties.sewageName ||
          a.properties.sectionName ||
          a.properties.address ||
          a.properties.pumpName ||
          a.properties.projectAbbreviation;
      })
  );

  let types = {};
  list
    .map((i) => i.data && i.data.features)
    .filter(Boolean)
    .flat(Infinity)
    .forEach((feature) => {
      if (!!!feature || !!!feature.properties) return;
      feature.properties.geometry = 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 = newfiberMap.getLayers().filter((i) => i.newfiberId == key)[0];
  if (!!!layer) {
    layer = newfiberMap.unLoadLayers.filter((i) => i.newfiberId == key)[0];
    layer && newfiberMap.addLayer(layer);
  }
  if (layer) layer.setData(json);
  setLegendData([{ data: json, layername: key, type: 'point' }]);
};

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

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);
      console.log(a.features[0]);
    })
  );
};

watch(
  () => props.PostionValue,
  (newVal, oldVal) => {
    console.log(`地图中接手到的最新坐标位置`, newVal);
    console.log('地图渲染轨迹----飞哥');
  },
  {
    deep: true,
  }
);

//添加河流标注
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': 12,
        '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,
        'text-allow-overlap': true,
      },
    });
};
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');
  newfiberMap.destroy();
  newfiberMap = null;
});
</script>
<style lang="less" scoped>
.mapPage {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0px;
  top: 0px;
  z-index: 10;
  background: lavender;
}

#cesiumContainer {
  width: 100%;
  height: 100%;
  position: absolute;
}
.l7-control-mouse-location {
  background: none;
}
.l7-control-mouse-location {
  color: #ffffff;
}
</style>