Newer
Older
DH_Apicture / src / components / Map / MapBox.vue
@ZZJ ZZJ on 30 Nov 22 KB 合并
<template>
  <MapBox :initJson="props.initJson" :loadCallback="getModalData" @map-click="mapClickEvt" v-show="MapShow"> </MapBox>
  <!-- <div id="trajectory-popup" ref="trajectory">1111</div> -->
  <div style="width: 700px; height: 350px" ref="streetSpace1" id="streetSpace">
    <streetSpace :location="datas.location"></streetSpace>
  </div>
</template>

<script setup name="Map">
import bus from '@/bus';
import request from '@/utils/request';
import MapBox from '@/components/Map/Map';
import { getBaseListPoint } from '@/api/MonitorAssetsOnMap';
import { supervisionRealinformationList } from '@/api/internetVehicles';
import useUserStore from '@/store/modules/user';
import { reactive, onMounted, onBeforeUnmount, nextTick, defineProps, watch } from 'vue';
import streetSpace from '@/components/Map/streetSpace';
import gq_line from '../../../public/static/libs/mapbox/json/gq_line.json';
import ys_flow from '../../../public/static/libs/mapbox/json/ys_flow.json';
import line from '../../../public/static/libs/mapbox/json/line.json';
import point from '../../../public/static/libs/mapbox/json/point.json';
import { MapboxOverlay } from '@deck.gl/mapbox';
import { LineLayer, GeoJsonLayer } from '@deck.gl/layers';
import { TripsLayer, Tile3DLayer } from '@deck.gl/geo-layers';
import { Tiles3DLoader } from '@loaders.gl/3d-tiles';
const appStore = useUserStore();
const MapShow = ref(true);
const props = defineProps({
  // 数据id
  initJson: {
    type: String,
    default: () => '/static/libs/mapbox/style/wh_dhgx.json',
  },
  loadCallback: {
    type: Function,
    default: () => function () {},
  },
});
const datas = reactive({
  location: [],
  isOpenPanorama: false,
});
const { proxy } = getCurrentInstance();
const refreshTimer = ref(null);
const default_params = {
  point: {
    key: 'point',
    prevId: null,
  },
  sx_wn_hm_monitoring: {
    key: 'sx_wn_hm_monitoring',
    prevId: null,
  },
  town: {
    key: '乡镇',
    c_key: '村',
    prevId: null,
  },
  hupo: {
    key: '湖泊',
    prevId: null,
  },
  gangqu: {
    key: '港渠',
    prevId: null,
  },
  hb_wh_dhgx_merge: {
    key: 'hb_wh_dhgx_merge',
    children: {
      psfq: { key: '排水分区' },
    },
    prevId: null,
  },
  海绵型水系: { color: 'rgba(35,184,153,1)' },
  海绵建筑与社区: { color: 'rgba(255,119,125,1)' },
  海绵型道路广场: { color: 'rgba(255,152,4,1)' },
  管网及泵站: { color: 'rgba(0,153,68,1)' },
  海绵型公园绿地: { color: 'rgba(223,214,20,1)' },
  flow: { color: 'rgba(255,255,255,1)' },
  rain: { color: 'rgba(255,255,255,1)' },

  water_level: { color: 'rgba(255,255,255,1)' },
  waterlogging: { color: 'rgba(255,255,255,1)' },

  rain_bz: { color: 'rgba(255,255,255,1)' },
  sxt: { color: 'rgba(255,255,255,1)' },
  WSCLC: { color: 'rgba(255,255,255,1)' },
  overflow_outfall: { color: 'rgba(255,255,255,1)' },

  rainfall: { color: 'rgba(223,214,20,1)' },
  pipeline: { color: 'rgba(223,214,20,1)' },
  drain_outlet: { color: 'rgba(223,214,20,1)' },
};
window.mapInitBusName = 'mapInitBusName';
const mapClickEvt = (lngLat, properties, layerId) => {
  datas.isOpenPanorama &&
    (() => {
      setPopupDom('proxy.$refs.streetSpace1', 2);
      newfiberMap.popup1.setLngLat(lngLat).addTo(newfiberMap.map);
      datas.location = lngLat;
    })();

  console.log('properties', properties, layerId);
  // 图层点击事件
  if (properties) bus.emit('FenQuClick', properties);
  clearTrajectory();
  clearTemporaryData();
  proxy.$emit('map-click1', lngLat, properties, layerId);
  const { town, hupo, gangqu, hb_wh_dhgx_merge } = default_params;
  const { setLayerVisible, setHighlight, setGeoJSON, removeMapDatas } = events_params;
  const _keys = ['rain_water_pump_station_info', 'sewage_pump_station_info'];

  (() => {
    setHighlight_(properties);
    newfiberMap
      .getLayers()
      .filter(i => i.newfiberId == '村域边界')[0]
      .setData(turf.featureCollection([]));
    if (town.prevId) {
      busEmit(setLayerVisible.key, { layername: town.key, isCheck: true });
      busEmit(setLayerVisible.key, { layername: town.prevId, isCheck: false });
      town.prevId = null;
    }
    busEmit(
      removeMapDatas.key,
      _keys.map(k => k + 1)
    );
  })();
  (
    ({
      [town.key]: () => {
        newfiberMap
          .getLayers()
          .filter(i => i.newfiberId == '村域边界')[0]
          .setData(
            turf.featureCollection(
              newfiberMap.map.getSource('hb_wh_gxq_cun2')._data.features.filter(i => i.properties.type == properties.name)
            )
          );
        busEmit(setLayerVisible.key, { layername: town.key, isCheck: false });
        busEmit(setLayerVisible.key, { layername: properties.name, isCheck: true });
        town.prevId = properties.name;
      },
      [hupo.key]: () => {
        if (hupo.prevId) {
          busEmit(setLayerVisible.key, {
            layername: hupo.prevId,
            isCheck: false,
            values: [hupo.prevId, ['严东湖', '严西湖'].join(',')],
          });
          hupo.prevId = null;
          bus.emit('removeMapDatas', ['outlet_info1']);
        }
        const keys = ['outlet_info', '村域边界', 'lake'];
        const specialKeys = ['严东湖', '严西湖'];
        newfiberMap
          .getLayers()
          .filter(i => i.newfiberId == keys[1])[0]
          .setData(turf.featureCollection(gq_line.features.filter(i => i.properties.w_id == properties.name)));
        let features = newfiberMap.map
          .getSource('point')
          ._data.features.filter(
            i =>
              i.properties.type == keys[0] && i.properties.waterBodyType == keys[2] && i.properties.waterBodyId == properties.pid
          )
          .map(i => _.cloneDeep(i));
        features.forEach(i => (i.properties.type = i.properties.type + '1'));
        busEmit(events_params.setGeoJSON.key, {
          json: turf.featureCollection(features),
          key: keys[0] + 1,
        });
        const values = [specialKeys.includes(properties.name) ? specialKeys.join(',') : properties.name];
        busEmit(setLayerVisible.key, {
          layername: properties.name,
          isCheck: true,
          values,
        });
        hupo.prevId = properties.name;
      },
      [gangqu.key]: () => {
        if (gangqu.prevId) {
          gangqu.prevId = null;
          bus.emit('removeMapDatas', ['outlet_info1']);
        }
        const keys = ['outlet_info', '村域边界', 'channel'];
        newfiberMap
          .getLayers()
          .filter(i => i.newfiberId == keys[1])[0]
          .setData(turf.featureCollection(gq_line.features.filter(i => i.properties.name == properties.name)));
        let features = newfiberMap.map
          .getSource('point')
          ._data.features.filter(
            i =>
              i.properties.type == keys[0] && i.properties.waterBodyType == keys[2] && i.properties.waterBodyId == properties.pid
          )
          .map(i => _.cloneDeep(i));
        features.forEach(i => (i.properties.type = i.properties.type + '1'));
        busEmit(events_params.setGeoJSON.key, {
          json: turf.featureCollection(features),
          key: keys[0] + 1,
        });
        gangqu.prevId = properties.name;
      },
      [hb_wh_dhgx_merge.key]: () => {
        if (properties.layer == hb_wh_dhgx_merge.children.psfq.key) {
          const layerSplit = properties.c_layer.split('_');
          let geometry = Terraformer.WKT.parse(properties.geometry);

          busEmit(setHighlight.key, []);
          const type = _.chunk(layerSplit[1], 2)[0].join('');
          let pType = type == '雨水' ? 'YS' : 'WS';
          pType == 'YS' ? ys_flow(properties, true) : ws_flow(properties);
          if (layerSplit[2] != 3) return mapCenterByData(turf.bbox(geometry));
          let features = newfiberMap.map
            .getSource('hb_wh_dhgx_pipe_line_n_y_w')
            ._data.features.filter(i => i.properties[type + '系统'] == properties.name && i.properties['管段类型'] == pType);
          let pFeatures = newfiberMap.map
            .getSource('point')
            ._data.features.filter(i => _keys.includes(i.properties.type) && (i.properties.pointTypeName || '').includes(type));
          let p_features = turf.pointsWithinPolygon(turf.featureCollection(pFeatures), geometry);
          p_features.features.forEach(i => (i.properties.type = i.properties.type + 1));
          busEmit(setGeoJSON.key, { json: p_features });
          console.log('features', p_features, pFeatures);
          busEmit(setHighlight.key, turf.flatten(turf.featureCollection(features)).features);
        }
      },
    })[layerId] ||
    function () {
      //newfiberMap.map.easeTo(newfiberMap.config_.params.init);
    }
  )();

  function ys_flow(properties, visible) {
    const keys = ['雨水系统流向', '雨水系统流向1'];
    keys.forEach(key => busEmit(setLayerVisible.key, { layername: key, isCheck: visible }));
    setHighlight_(properties);
  }

  function ws_flow(properties) {
    const keys_ = ['雨水', '污水'];
    const keys = ['1_泵站', '1_污水处理厂', '分区流向', '分区流向1'];
    bus.emit('removeMapDatas', keys);
    newfiberMap
      .getLayers()
      .filter(i => i.newfiberId == keys[3])[0]
      .getSource()
      .setData(turf.featureCollection([]));
    let key = (properties.c_layer || '').includes(keys_[0]) ? keys_[0] : keys_[1];
    if (properties.pointTypeName) key = keys_[1];
    const nameKey = '龙王咀' || properties.name.substring(0, 2);
    let features = line.features.filter(i => i.properties.area.includes(key) && i.properties.name.includes(nameKey));
    let features1 = point.features.filter(i => i.properties.area.includes(key) && i.properties.system.includes(nameKey));
    let points = _.groupBy(features1, a => a.properties.type);
    features.forEach(i => {
      i.properties.type = keys[2];
      i.properties.color = key == keys_[0] ? 'rgba(21,127,176,1)' : 'rgba(255,0,0,1)';
    });
    Object.keys(points).map(key =>
      bus.emit('setGeoJSON', {
        json: turf.featureCollection(
          points[key].map(i => ({
            type: i.type,
            geometry: i.geometry,
            properties: { ...i.properties, type: '1_' + key },
          }))
        ),
        key: '1_' + key,
      })
    );
    bus.emit('setGeoJSON', { json: turf.featureCollection(features), key: keys[2] });
    newfiberMap
      .getLayers()
      .filter(i => i.newfiberId == keys[3])[0]
      .getSource()
      .setData(turf.featureCollection(features));
    setHighlight_(properties);
  }
};

function setHighlight_(properties = {}) {
  const temporary = 'temporary';
  bus.emit('removeMapDatas', [temporary]);
  if (!properties.geometry) return;
  let geojson = turf.polygonToLine(Terraformer.WKT.parse(properties.geometry));
  geojson = geojson.features ? geojson : turf.featureCollection([geojson]);
  geojson.features.forEach(i => (i.properties = { color: 'rgba(255,255,0,1)', type: temporary }));
  bus.emit('setGeoJSON', { json: geojson, key: temporary });
  newfiberMap
    .getLayers()
    .filter(i => i.newfiberId == '村域边界')[0]
    .setData(geojson);
}

const getModalData = () => {
  isClockInRange();
  const { setLayerVisible, setHighlight } = events_params;
  Object.keys(events_params)
    .filter(key => events_params[key].method)
    .forEach(key => busOn(events_params[key].key, events_params[key].method));
  // 获取地图项目数据
  dataToMap({});
  //5分钟刷新一次实时数据1000 * 60 * 5)
  /*  refreshTimer.value = setInterval(() => {
    dataToMap({ params: { rainfall: {}, pipeline: {}, drainUutlet: {} } });
  }, 1000 * 60 * 5);*/
  createPopup();
  busEmit(events_params.closeAllLayer.key);
  proxy.$emit('loadCallback');
  ww();
  ysFlow();
};

const ysFlow = () => {
  const key = '雨水系统流向';
  // let features = line.features.filter(i => key.includes(i.properties.area));
  // ys_flow.features = ys_flow.features.concat(features).map(i => ({ ...i, properties: { ...i.properties, color: 'rgba(49,254,223,1)', name: undefined } }));
  newfiberMap
    .getLayers()
    .filter(i => i.newfiberId == key)[0]
    .setData(ys_flow);
  busEmit(events_params.setGeoJSON.key, { json: ys_flow, key: key + 1 });
};

const ww = () => {
  const keys = ['尾水路径'];
  let features = newfiberMap.map
    .getSource('hb_wh_dhgx_merge')
    ._data.features.filter(i => i.properties.c_layer.includes(keys[0]) && i.properties.geometry_type == 2);
  busEmit(events_params.setGeoJSON.key, {
    json: turf.featureCollection(features),
    key: keys[0],
  });
};

let prevObj = null;
const panelDataToMap = obj => {
  // debugger
  const { setLayerVisible, setHighlight } = events_params;
  // if (prevObj != null) busEmit(setLayerVisible.key, { layername: prevObj.type, isCheck: false });
  busEmit(setHighlight.key, []);
  // busEmit(setLayerVisible.key, { layername: obj.type, isCheck: true });
  // debugger;
  let features = ['point', 'linestring', 'polygon', 'hb_wh_dhgx_merge']
    .map(key =>
      newfiberMap.map
        .getSource(key)
        ._options.data.features.filter(
          i => (i.properties.name || '').includes(obj.name) && (obj.id ? obj.id == i.properties.pid : true)
        )
    )
    .flat();
  let feature = features.filter(i => i.properties.name == obj.name)[0] || features[_.random(0, features.length - 1)];
  if (!feature) return;
  busEmit(setHighlight.key, [feature]);
  mapCenterByData(turf.bbox(feature));
};

const mapCenterByData = bbox => {
  newfiberMap.map.fitBounds(
    [
      [bbox[0], bbox[1]],
      [bbox[2], bbox[3]],
    ],
    { padding: 50, offset: [100, 10], maxZoom: 18, pitch: 0, duration: 500 }
  );
};
const trajectoryToMap = data => {
  clearTrajectory();
  const fields = { lng: 'l', lat: 'a' };
  mapCenterByData([data[0]['l'], data[0]['a'], data[1]['l'], data[1]['a']].map(Number));
  newfiberMap.map.trackLayer = new mapboxgl1.TrackLayer(newfiberMap.map, data, fields, (properties, index) => {
    const lng = properties[fields.lng];
    const lat = properties[fields.lat];
    if (!(index % 50)) {
      newfiberMap.map.flyTo({
        center: [lng, lat],
        bearing: newfiberMap.map.getBearing(),
        pitch: newfiberMap.map.getPitch(),
        zoom: newfiberMap.map.getZoom(),
      });
    }
    /*        setPopupDom('proxy.$refs.trajectory', 1);
                            newfiberMap.popup.setLngLat([lng,lat]).addTo(newfiberMap.map);*/
  });
};

const clearTrajectory = () => {
  if (newfiberMap.map.trackLayer) newfiberMap.map.trackLayer.destory();
  if (newfiberMap.popup) newfiberMap.popup.remove();
};

const dataToMap = async ({ params, callback }) => {
  const { setLayerVisible, beansToMap } = events_params;
  const data_default_params = {
    sites: {
      method: getBaseListPoint,
      fields: { geometry: 'geometry', name: 'name' },
      groupMethod: data =>
        _.groupBy(
          data
            .map(i => i.data)
            .flat()
            .filter(i => i.geometry)
            .map(item => ({ ...item })),
          v => v.pointType + (v.connectType ? '_' + v.connectType : '')
        ),
    },
    //车辆
    cheliang: {
      method: supervisionRealinformationList,
      fields: { lng: 'longitude', lat: 'latitude', name: 'plateNumber' },
      groupMethod: data =>
        _.groupBy(
          data.supervisionRealinformationList
            .filter(i => i.longitude && i.latitude)
            .map(item => ({ ...item, type: item.vehicleCategory + item.status })),
          v => v.type
        ),
    },
  };
  let keys = Object.keys(params || data_default_params);
  const results = await Promise.all(
    keys.map((k, idx) => data_default_params[k].method((params || {})[k] || data_default_params[k].mPrams))
  );
  results.forEach((result, idx) => {
    const data = result.data;
    const k = keys[idx];
    if (!data) return;
    bus.emit('changeData');
    const groups = data_default_params[k].groupMethod(data);
    const g_keys = Object.keys(groups);
    bus.emit('removeMapDatas', g_keys);
    g_keys.forEach(key =>
      busEmit(beansToMap.key, {
        beans: groups[key].map(i => ({
          ...i,
          color: (default_params[key] || {}).color,
        })),
        fields: data_default_params[k].fields,
        type: key,
      })
    );
  });

  callback && callback();
};

const createPopup = () => {
  newfiberMap.popup = new mapboxgl1.Popup({
    closeButton: false,
    closeOnClick: false,
  });
  newfiberMap.popup1 = new mapboxgl1.Popup({
    closeButton: false,
    closeOnClick: false,
  });
};

const setPopupDom = (dom, offset) => {
  f();
  nextTick(f);
  function f() {
    console.log('eval(dom)', eval(dom));
    newfiberMap.popup1.setDOMContent(eval(dom));
    newfiberMap.popup1.setOffset(offset);
  }
};

function filterGeometryNotEmpty(inputData) {
  return inputData.map(item => {
    // 过滤掉每个对象中的 data 数组里 geometry 为空的元素
    const filteredData = item.data.filter(dataPoint => dataPoint.geometry !== '');
    return {
      ...item,
      data: filteredData,
    };
  });
}

//路径规划
const pathPlanning = async (origin = '116.481028,39.989643', destination = '116.465302,40.004717', callback) => {
  const origin_ = origin.split(',').map(Number);
  const destination_ = destination.split(',').map(Number);
  if (origin_.length != 2 || destination_.length != 2) return console.log('输入参数错误:', origin, destination);
  const results = await request(
    `/amap/v3/direction/driving?origin=${origin}&destination=${destination}&extensions=all&output=json&key=74f1b47f7fea1971354edb2dfacb3982`
  );
  if (!results.route.paths[0]) return console.log('暂无路径!');
  callback &&
    callback(
      turf.featureCollection(
        results.route.paths[0].steps.map(i =>
          turf.feature(
            Terraformer.WKT.parse(
              `LINESTRING(${i.polyline
                .split(';')
                .map(i => i.split(',').join(' '))
                .join(',')})`
            ),
            i
          )
        )
      )
    );
};

//判断是否在打卡点内
const isClockInRange = (
  currentLocation = 'POINT(109.41360117253636 34.49038724464877)',
  ranges = [
    'POINT(109.43167853335872 34.51345940211415)',
    'POINT(109.46797592891363 34.51145239795833)',
    'POINT(109.44903576574815 34.50165755773118)',
  ],
  rVal = 500
) => {
  const feature = { ...Terraformer.WKT.parse(currentLocation) };
  return (
    ranges
      .map(i => turf.buffer({ ...Terraformer.WKT.parse(i) }, rVal / 1000))
      .map(i => turf.booleanContains(i, feature))
      .filter(Boolean)[0] || false
  );
};

const clearTemporaryData = () => {
  const { setLayerVisible, removeMapDatas } = events_params;
  const keys_ = [
    '问题管线',
    '1_泵站',
    '1_污水处理厂',
    '分区流向',
    '分区流向1',
    'rainwater_pipeline_water_level',
    'rainwater_pipeline_water_level_GWGSWYX',
    'outlet_info1',
    'temporary',
    'highlight_linestring',
    'highlight_polygon',
    'highlight_point',
  ];
  const hideKeys = ['雨水系统流向', '雨水系统流向1'];
  bus.emit(removeMapDatas.key, keys_);
  const keys = newfiberMap.config_.l7.filter(i => i.temporary).map(i => i.key);
  newfiberMap
    .getLayers()
    .filter(i => keys.includes(i.newfiberId))
    .forEach(i => i.setData({ type: 'FeatureCollection', features: [] }));
  hideKeys.forEach(i => busEmit(setLayerVisible.key, { layername: i, isCheck: false }));

  setHighlight_();
};

const remove3Dtiles = () => {
  newfiberMap.map._controls.filter(i => i._deck).forEach(i => i.setProps({ layers: [] }));
};

const load3DTiles = ({ id, url }) => {
  remove3Dtiles();
  let deckOverlay = null;
  deckOverlay = newfiberMap.map._controls.filter(i => i._deck)[0];
  if (!deckOverlay) {
    deckOverlay = new MapboxOverlay({
      interleaved: true,
      layers: [],
    });
    newfiberMap.map.addControl(deckOverlay);
  }
  const layers = deckOverlay._props.layers;
  deckOverlay.setProps({
    layers: [
      ...layers,
      new Tile3DLayer({
        id: id,
        name: id,
        data: url,
        loader: Tiles3DLoader,
        extruded: true, // 设置3D功能
        opacity: 1, // 设置透明度
        loadOptions: {
          '3d-tiles': {
            loadGLTF: true,
            decodeQuantizedPositions: false,
            isTileset: 'auto',
            assetGltfUpAxis: null,
          },
        },
        pickable: true, // 设置可选取
        onTilesetLoad: tileset => {
          const { cartographicCenter, zoom } = tileset;
          deckOverlay.setProps({
            initialViewState: {
              longitude: cartographicCenter[0],
              latitude: cartographicCenter[1],
              zoom,
            },
          });
        },
        pointSize: 2,
      }),
    ],
  });
};

const busEmit = (event, params) => bus.emit(event, params);

const busOn = (event, func) => bus.on(event, func);

const busOff = event => bus.off(event);
//添加临时动态线
const addDynamicLine = (c_layer, c_layer1) => {
  if (newfiberMap.getLayerByName('dynamicLine')) {
    newfiberMap.removeLayer(newfiberMap.getLayerByName('dynamicLine'));
  }
  let dynamicLineJson = turf.featureCollection(
    newfiberMap.map
      .getSource('sx_wn_hm_merge')
      ._data.features.filter(
        feature => feature.properties.c_layer.includes(c_layer) && feature.properties.c_layer.includes(c_layer1)
      )
  );
  console.log(c_layer, dynamicLineJson);
  let layer = new mapboxL7.LineLayer({
    name: 'dynamicLine',
  })
    .source(dynamicLineJson)
    .size(3)
    .shape('line')
    .color('color')
    .animate({
      interval: 1,
      duration: 2,
      trailLength: 0.8,
    });
  newfiberMap.addLayer(layer);
};
const events_params = {
  removeMapDatas: { key: 'removeMapDatas' },
  setGeoJSON: { key: 'setGeoJSON' },
  setLayerVisible: { key: 'setLayerVisible' },
  beansToMap: { key: 'beansToMap' },
  closeAllLayer: { key: 'closeAllLayer' },
  setHighlight: { key: 'setHighlight' },
  dataToMap: { key: 'dataToMap', method: dataToMap },
  pathPlanning: { key: 'pathPlanning', method: pathPlanning },
  panelDataToMap: { key: 'panelDataToMap', method: panelDataToMap },
  trajectoryToMap: { key: 'trajectoryToMap', method: trajectoryToMap },
  clearTrajectory: { key: 'clearTrajectory', method: clearTrajectory },
  clearTemporaryData: { key: 'clearTemporaryData', method: clearTemporaryData },
  load3DTiles: { key: 'load3DTiles', method: load3DTiles },
  remove3Dtiles: { key: 'remove3Dtiles', method: remove3Dtiles },
  isOpenPanorama: { key: 'isOpenPanorama', method: flag => (datas.isOpenPanorama = flag) },
};

onMounted(() => {
  bus.on('YQ_head', val => {
    if (val == false) {
      MapShow.value = false;
    } else {
      MapShow.value = true;
    }
  });
});

onBeforeUnmount(() => {
  bus.off('YQ_head');
  Object.keys(events_params)
    .filter(key => events_params[key].method)
    .forEach(key => busOff(events_params[key].key));
  clearInterval(refreshTimer.value); // 清除定时器
  refreshTimer.value = null;
});
</script>

<style lang="scss">
#Map {
  width: 100%;
  height: 100%;
}
</style>