• 功能场景:鼠标在地图上移动获取的实时坐标,并且点击之后会进行坐标系转换

  • 效果如下
    在这里插入图片描述
    在这里插入图片描述

使用到的技术点

  • 地图:mapbox
  • 使用的工具:Proj4

封装成组件(代码如下)

<script>
import { reactive, computed, toRefs, watch, onUnmounted } from 'vue';
// 状态管理依赖
import { useMapStore } from '../../stores/map';
import { storeToRefs } from 'pinia';
// 组件依赖
import _ from 'lodash-es';
import { GET_MAPBOX_MAP } from '../../common/common-map-fun';
import { degree2dms } from '../../common/common-helper';
import proj4 from 'proj4';
// * 国家 2000 投影坐标,3 度带
// eslint-disable-next-line
proj4.defs('EPSG:4546', '+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs');

let handler = null;

export default {
  name: 'MapPoints',

  setup() {
    const state = reactive({
      system: '4546',
      position: { lat: 'N', lng: 'N', x: 'N', y: 'N', zoom: 'N' },
      degree2dms,
    });

    const $mapStore = useMapStore();

    const { mode, initialized } = storeToRefs($mapStore);

    const calcTwoVariable = computed(() => {
      return { mode, initialized };
    });

    // 二维地图获取缩放级别
    const handleZoom = () => {
      state.position = {
        ...state.position,
        zoom: String(Math.round(GET_MAPBOX_MAP().getZoom())),
      };
    };

    // 三维地图获取经纬度坐标
    const method = {
      handleLngLat: _.debounce(function (e) {
        const xy = proj4('EPSG:4546', [e.lngLat.lng, e.lngLat.lat]);
        // const xy = [e.lngLat.lng, e.lngLat.lat];

        state.position = { ...state.position, ...e.lngLat, x: xy[0], y: xy[1] };
      }, 20),
    };
    const { handleLngLat } = method;

    watch(
      calcTwoVariable,
      (val) => {
        state.position = { lat: 'N', lng: 'N', x: 'N', y: 'N', zoom: 'N' };

        // * 二维地图
        if (val.mode.value == '2d' && val.initialized.value.includes('2d')) {
          const map = GET_MAPBOX_MAP();

          state.position = {
            ...map.getCenter(),
            zoom: map.getZoom(),
          };

          // 鼠标位置信息
          map.on('mousemove', handleLngLat);
          map.on('zoomend', handleZoom);
        }
      },
      { deep: true, immediate: true },
    );

    onUnmounted(() => {
      GET_MAPBOX_MAP() && GET_MAPBOX_MAP().off('mousemove', handleLngLat);
      GET_MAPBOX_MAP() && GET_MAPBOX_MAP().off('zoomend', handleZoom);

      handler && handler.destroy();
      handler = null;
    });

    return {
      ...toRefs(state),
      initialized,
      mode,
      calcTwoVariable,
      handleZoom,
    };
  },
};
</script>
<template>
  <div class="roots" title="切换坐标系" @click="system === 'wgs84' ? (system = '4546') : (system = 'wgs84')">
    <template v-if="system === 'wgs84'">
      <span>{{ `东经:${degree2dms(parseFloat(position.lng).toFixed(5))}` }}</span>
      <span>{{ `北纬:${degree2dms(parseFloat(position.lat).toFixed(5))}` }}</span>
    </template>
    <template v-else>
      <span>{{ `X:${parseFloat(position.x).toFixed(5)}` }}</span>
      <span>{{ `Y:${parseFloat(position.y).toFixed(5)}` }}</span>
    </template>
    <span>{{ mode === '3d' ? `级别:${position.zoom}` : `级别:${String(position.zoom)}` }}</span>
  </div>
</template>

<style lang="scss" scoped>
.roots {
  position: absolute;
  cursor: pointer;
  bottom: 8px;
  left: 50%;
  display: flex;
  flex-direction: row;
  height: 15px;
  padding: 16px 25px;
  line-height: 0;
  font-size: 16px;
  color: rgb(255, 255, 255);
  font-weight: lighter;
  font-weight: 400;
  background-color: rgba(0, 0, 0, 0.54);
  border-radius: 5px;
  transform: translateX(-50%);
  z-index: 99;
  & > span:not(:last-child) {
    margin-right: 16px;
  }
}
</style>

Logo

欢迎加入我们的广州开发者社区,与优秀的开发者共同成长!

更多推荐