Newer
Older
KaiFengPC / src / components / mapBoxSelectPosition / mapBoxSelectPosition.vue
@jimengfei jimengfei on 31 Jul 10 KB updata
<template>
  <div class="mapDrawTool">
    <div id="mapboxDrawContainer">
      <div id="nf-address-search-input" v-if="inputShow">
        <el-input
          clearable
          id="pickerInput"
          placeholder="请输入位置名称"
          v-model="inputText"
          :prefix-icon="Search"
          style="width: 300px"
          @input="inputGetAddress()"
        />
      </div>
      <div class="addressOption" v-if="addressListIsShow">
        <div class="addressOptionItem" v-for="item in addressList" @click="clickAddress(item)">
          {{ item.formatted_address }}
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import bus from '@/bus';
import axios from 'axios';
import request from '@/utils/request';
import kaifengWaterLabel1 from '@/assets/geojson/kaifeng/kaifengWaterLabel1.json';
import kaifengWater from '@/assets/geojson/kaifeng/kaifengWater.json';
import WaterAnalysis_icon from '@/assets/images/gisMap/in.png';
import { nextTick } from 'vue';
export default {
  components: {},
  props: {
    initJson: {
      type: String,
      default: () => '/static/libs/mapbox/style/floodOneMap.json',
    },
    isNeedInput: {
      type: Boolean,
      default: true,
    },
    isCanClick: {
      type: Boolean,
      default: true,
    },
    previousPoint: {
      type: String,
      default: '',
    },
    previousPointName: {
      type: String,
      default: '',
    },
  },
  setup(props, event) {
    const allData = reactive({
      inputText: '',
      addressList: [],
      addressListIsShow: false,
      pointGeometry: '',
      inputShow: true,
    });
    let map = null;
    let config = null;
    const initeMap = async () => {
      config = (await axios.get(props.initJson)).data;
      let { sprites, l7 } = config.params;
      window.mapBoxSelectPositionMap = new mapboxL7.Scene({
        id: 'mapboxDrawContainer',
        map: new mapboxL7.Mapbox({
          style: config.params.init.style,
          center: config.params.init.center,
          zoom: config.params.init.zoom,
        }),
      });
      mapBoxSelectPositionMap.map.load = false;
      map = mapBoxSelectPositionMap.map;
      map.ogcLayers = [];
      mapBoxSelectPositionMap.unLoadLayers = [];
      (sprites || []).forEach(url => {
        map.style._loadSprite(url.includes('http') ? url : window.location.href.split('#')[0] + url);
      });
      ((l7 || []).images || []).forEach(item =>
        mapBoxSelectPositionMap.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)];
            },
          });
          mapBoxSelectPositionMap.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': '#0c3b7a',
              },
            });

          addWaterLabel();
          props.loadCallback && props.loadCallback();

          let { pitch, center } = config.params.init;
          pitch && mapBoxSelectPositionMap.map.setPitch(pitch);
          center && mapBoxSelectPositionMap.map.setCenter(center);

          mapBoxSelectPositionMap.map.load = true;
        });
      }, 200);

      if (props.isCanClick) {
        map.on('click', e => {
          let drewPoint = turf.featureCollection([turf.point([e.lngLat.lng, e.lngLat.lat])]);
          allData.pointGeometry = e.lngLat.lng + ',' + e.lngLat.lat;
          getAddressByLngLat(...NewFiberMap.CoordTransform.wgs84togcj02(e.lngLat.lng, e.lngLat.lat)).then(res => {
            allData.inputText = res.formatted_address;
            bus.emit('getDrawPoint', [allData.pointGeometry, res.formatted_address]);
            drewPoint.features[0].properties.name = res.formatted_address;
            addPointToMap(drewPoint);
          });
        });
      }
    };

    //添加河流标注
    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',
          },
          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('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(0,0,0,1)',
            'text-color': 'rgba(0,167,210,1)',
            'icon-opacity': 1,
            'text-halo-width': 1,
          },
        });
    };
    //根据经纬度获取地名
    const getAddressByLngLat = async (lng, lat) => {
      let data = await request({
        url: `/amap/v3/geocode/regeo`,
        method: 'GET',
        params: {
          location: `${lng},${lat}`,
          key: '5f806b4c107901cd999af4c4931a8882',
          radius: 1000,
          extensions: 'all',
          output: 'json',
        },
      });
      if (data.info === 'OK') return data.regeocode;
    };
    //输入框获取地址
    const inputGetAddress = async () => {
      if (allData.inputText === '') {
        allData.addressListIsShow = false;
      }
      let data = await request({
        url: `/amap/v3/geocode/geo`,
        method: 'GET',
        params: {
          address: allData.inputText,
          city: 'kaifeng',
          key: '5f806b4c107901cd999af4c4931a8882',
          radius: 1000,
          output: 'json',
        },
      });
      if (data.info === 'OK') {
        allData.addressListIsShow = true;
        allData.addressList = data.geocodes;
      }
    };
    //搜索地址点击
    const clickAddress = value => {
      if (!!value.location) {
        let lonlat = value.location.split(',').map(Number);
        let lonlat_84 = NewFiberMap.CoordTransform.gcj02towgs84(lonlat[0], lonlat[1]);
        let drewPoint = turf.featureCollection([turf.point(lonlat_84)]);
        allData.pointGeometry = lonlat_84[0] + ',' + lonlat_84[1];
        bus.emit('getDrawPoint', [allData.pointGeometry, value.formatted_address]);
        drewPoint.features[0].properties.name = value.formatted_address;
        addPointToMap(drewPoint);
        map.easeTo({
          center: lonlat_84,
          zoom: 15,
        });
        allData.inputText = value.formatted_address;
        allData.addressListIsShow = false;
      }
    };
    //渲染点位
    const addPointToMap = geojson => {
      if (!map.getLayer('drewPoint')) {
        map.loadImage(WaterAnalysis_icon, function (error, image) {
          if (error) throw error;
          map.addImage('drewPoint_icon', image);
          map.addSource('drewPoint', {
            type: 'geojson',
            data: geojson,
          });
          map.addLayer({
            id: 'drewPoint',
            type: 'symbol',
            source: 'drewPoint',
            layout: {
              'text-field': ['get', 'name'],
              'text-font': ['KlokanTech Noto Sans Regular'],
              'text-offset': [0, -3],
              'icon-image': 'drewPoint_icon', // 你的自定义图标名称
              'icon-size': 0.2, // 图标大小
              'icon-anchor': 'center', // 图标锚点位置
            },
            paint: {
              'text-color': 'rgba(18, 150, 219,1)',
              'text-halo-color': 'rgba(213, 242, 247,1)',
              'text-halo-width': 2,
            },
          });
        });
      } else {
        map.getSource('drewPoint').setData(geojson);
      }
    };
    watch(
      () => [props.previousPoint, props.previousPointName],
      val => {
        if (!!val.length) {
          let initeTimeout = setTimeout(() => {
            let drewPoint = turf.featureCollection([turf.point(val[0].split(',').map(Number))]);
            drewPoint.features[0].properties.name = val[1];
            addPointToMap(drewPoint);
            map.easeTo({
              center: val[0].split(',').map(Number),
              zoom: 14,
            });
            clearTimeout(initeTimeout);
          }, 1000);
        }
      }
    );
    onMounted(() => {
      initeMap();
      nextTick(() => {
        allData.inputShow = props.isNeedInput;
      });
    });

    onBeforeUnmount(() => {
      mapBoxSelectPositionMap.destroy();
      mapBoxSelectPositionMap = null;
    });

    return {
      ...toRefs(allData),
      initeMap,
      inputGetAddress,
      clickAddress,
    };
  },
};
</script>
<style lang="scss">
.mapDrawTool {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0px;
  top: 0px;
  z-index: 10;
  background: lavender;
  #mapboxDrawContainer {
    width: 100%;
    height: 100%;
    position: absolute;
  }
  .l7-control-mouse-location {
    background: none;
  }
  .l7-control-mouse-location {
    color: #ffffff;
  }
  #nf-address-search-input {
    position: absolute;
    top: 20px;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    z-index: 100;
    background: rgba(255, 255, 255, 1);
    margin-left: 20px;
  }
  .addressOption {
    position: absolute;
    top: 53px;
    z-index: 100;
    background: rgba(255, 255, 255, 1);
    margin-left: 20px;
    height: 200px;
    width: 300px;
    background: rgba(0, 69, 101, 1);
    .addressOptionItem {
      font-size: 14px;
      font-family: PingFang SC;
      color: rgba(255, 255, 255, 1);
      margin-left: 10px;
      margin-top: 5px;
      cursor: pointer;
      &:hover {
        background: #08596a;
      }
    }
  }
}
</style>