data.v地图在线

 使用arco组件库,data.v在线地图数据,代码主要用来操作地图上的所示点。借鉴了他人代码和gpt,未简洁代码

<template>
  <div class="container">
    <a-card class="general-card" :bordered="false">
      <a-breadcrumb :routes="mapList">
        <template #item-render="{route, paths}">
          <a-link @click="renderMapEcharts(route.mapName)">
            {{ route.name }}
          </a-link>
        </template>
      </a-breadcrumb>
      <div style="height: 800px;">
        <Chart id="mycharts" :option="mapOption" :autoresize="true" @click="handleClick"
               @contextmenu="showContextMenu" />
        <div
          v-if="contextMenu.visible"
          class="context-menu"
          :style="{ left: `${contextMenu.position.x}px`, top: `${contextMenu.position.y}px`}"
        >
          <a-space>
            <a-button type="outline" size="small" @click="editDistrict(id)" :disabled="existData">编辑</a-button>
            <a-popconfirm content="确定删除该区域吗?" position="top" @ok="delDistrict(id)">
              <a-button type="outline" size="small" :disabled="existData">删除</a-button>
            </a-popconfirm>
            <a-button type="text" shape="circle" status="danger" @click="hideContextMenu">
              <icon-close />
            </a-button>
          </a-space>
        </div>
      </div>
    </a-card>
    <save-district ref="saveDistrict" />
  </div>
</template>
<script setup lang="ts">
import { registerMap, use } from "echarts/core";
import Chart from "vue-echarts";
import { CanvasRenderer } from "echarts/renderers";
import { EffectScatterChart, MapChart, ScatterChart } from "echarts/charts";
import {
  GridComponent,
  LegendComponent,
  TitleComponent,
  TooltipComponent,
  VisualMapComponent
} from "echarts/components";
import { inject, provide, ref } from "vue";
import { Notification } from "@arco-design/web-vue";
import SaveDistrict from "@/views/program/apply/district/component/saveDistrict.vue";
import { deleteStation, getMapData } from "@/api/program/district";

use([
  CanvasRenderer,
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GridComponent,
  VisualMapComponent,
  MapChart,
  ScatterChart,
  EffectScatterChart
]);
const reload: any = inject("reload");
const mapOption = ref();
const mapList = ref<any[]>([{
  mapName: "150000_full",
  name: "内蒙古自治区"
}]); // 记录地图


const getMapJson = async (mapName: string) => {
  const url = `https://geo.datav.aliyun.com/areas_v3/bound/${mapName}.json`;
  return await fetch(url).then(res => res.json());
};

const setOptions = (mapName: string, mapData: any) => {
  return {
    tooltip: {
      trigger: "item", // 触发类型为基于图形元素的触发
      formatter: function(params: any) {
        if (params.seriesType === "effectScatter") { // 确保处理的是scatter系列的数据
          const { name, value } = params.data; // 这里的value是站点的经纬度
          return `名称: ${name}<br>经纬度: ${value}`;
        }
      }
    },
    geo: {
      map: mapName,
      roam: true,
      select: false,
      zoom: 1.2,
      // layoutCenter: ["45%", "70%"],//页面位置和占比
      layoutSize: "100%",
      // 图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。
      selectedMode: "single",
      label: {
        show: true,
        backgroundColor: "transparent",
        position: "top",
        formatter: "{a}",
        color: "#7c9dd9",
        fontWeight: "bold"
      },
      itemStyle: {
        areaColor: "#323c48", // 默认区块颜色
        borderColor: "#9ea5af",
        borderWidth: 0.5,
        shadowBlur: 5, // 阴影模糊程度
        shadowColor: "rgba(0, 0, 0, 0.3)", // 阴影颜色,使用半透明黑色
        shadowOffsetX: 0, // 阴影在X轴方向上的偏移距离
        shadowOffsetY: 0  // 阴影在Y轴方向上的偏移距离
      },
      emphasis: {
        label: {
          fontSize: 14
        },
        itemStyle: {
          areaColor: "#596f9a", // 鼠标悬浮时的区块颜色
          borderColor: "#add1dc",
          borderWidth: 0.5,
          shadowBlur: 10, // 增加阴影模糊程度
          shadowColor: "rgba(0, 0, 0, 0.6)", // 使用更深一点的半透明黑色
          shadowOffsetX: 0,
          shadowOffsetY: 0
        }
      }

    },
    series: [
      // 数据
      {
        type: "map",
        map: mapName,
        roam: false,
        geoIndex: 0,
        select: false,
        data: mapData
      },
      {
        name: "位置",
        type: "effectScatter",
        coordinateSystem: "geo",
        data: mapData.flatMap(item => item.data),
        symbolSize: 3,
        label: {
          formatter: "  {b}",
          position: "right",
          show: true,
          color: "yellow"
        },
        itemStyle: {
          color: "yellow",
          shadowBlur: 10,
          shadowColor: "beige"
        },
        showEffectOn: "render",
        rippleEffect: {
          brushType: "stroke",
          scale: 8, // 增大波纹扩散比例
          period: 8, // 增加波纹动画周期,使其变化更慢,更容易看到
          color: "rgba(247,255,0,0.34)"// 调整波纹颜色,增加透明度,保证与站点颜色的对比度
        },
        zlevel: 1
      }
    ]
  };
};

const contextMenu = ref({
  visible: false,
  position: { x: 0, y: 0 }
});

const id = ref();
const existData = ref(false);
const operateType = ref();
const operateId = ref();

// 方法:显示上下文菜单
const showContextMenu = (event: MouseEvent) => {
  let parent = document.getElementById("mycharts");
  parent.oncontextmenu = () => false; // 阻止默认的右键菜单显示
  if (event.data.id != null) {
    contextMenu.value.position = { x: event.event.event.pageX - 55, y: event.event.event.pageY - 45 };
    contextMenu.value.visible = true; //弹框启用
    id.value = event.data.id;
    existData.value = false;
  } else {
    contextMenu.value.visible = false;
    existData.value = true;
  }
};

// 方法:隐藏上下文菜单
const hideContextMenu = () => {
  contextMenu.value.visible = false;
};

const renderMapEcharts = async (mapName: string) => {
  const mapJson = await getMapJson(mapName);
  registerMap(mapName, mapJson);
  // 去除集合在这之后的数据
  mapList.value.map((item, index) => {
    if (item.mapName === mapName) {
      mapList.value = mapList.value.splice(0, index + 1);
    }
  });
  const map = await getMapData();
  const mapdata = mapJson.features.map((item: { properties: any }) => {
    const tempValue = item.properties.center ? [...item.properties.center] : item.properties.center;
    //  调用接口 赋值data(没有按照父级关系绑定,有的点会在当前地图外展示出来
    const data = map.data.map(item => {
      return {
        id: item.id,
        name: item.name,
        value: item.value
      };
    });
    return {
      id: null,
      name: item.properties.name,
      value: tempValue, // 中心点经纬度
      adcode: item.properties.adcode, // 区域编码
      level: item.properties.level, // 层级
      data: data
    };
  });

  // 设置options并渲染
  mapOption.value = setOptions(mapName, mapdata);
};

renderMapEcharts("150000_full"); // 初始化绘制中国地图

// 点击下钻
const handleClick = (param: any) => {
  contextMenu.value.visible = false;
  // 只有点击地图才触发
  if (param.seriesType !== "map") return;
  if (param.data) {
    const { adcode, level, name } = param.data;
    const mapName = level === "district" ? adcode : adcode + "_full";
    // 防止最后一个层级被重复点击,返回上一级出错
    if (mapList.value[mapList.value.length - 1].mapName === mapName) {
      return Notification.warning("已下钻到底!");
    }
    mapList.value.push({
      mapName: mapName,
      name: name
    });
    renderMapEcharts(mapName);
  }
};


const saveDistrict = ref();
provide("operateInfo", {
  id: operateId,
  type: operateType
});
const showModal = (type: string, id: string) => {
  operateType.value = type;
  operateId.value = id;
  saveDistrict.value.handleClick();
};

const editDistrict = (id) => {
  showModal("edit", id);
  contextMenu.value.visible = false;
};

const delDistrict = async (id) => {
  await deleteStation(id);
  Notification.success("删除成功");
  contextMenu.value.visible = false;
  reload();
};

</script>

<style lang="less">
.container {
  padding: 0 20px 20px 20px;
}

.context-menu {
  background-color: transparent;
  border: none;
  position: fixed;
  z-index: 9999;
}

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值