echarts地理坐标系组件geo实现散点图绘制

5 篇文章 0 订阅

前言

需求图
在这里插入图片描述
在这里插入图片描述

需求:
1、绘制当前集团公司在世界分布的资产散点图,
2、双击点击中国地图,进入中国地图
3、右键返回世界地图
4、hover自定义tooltip,并且高亮所在地图区域

实现

  1. 准备世界地图坐标数据和我国地图坐标数据
    地理坐标系组件需要注册地图,我们需要导入并注册地图数据
    1、世界地图数据:worldGeoJson.ts
    2、中国地图数据:chinaGeoJson.ts
    坐标数据过大,我放入我的资源里面了,免费免积分
    
  2. 绘制以及option
    1、基础结构
    <template>
      <div id="ScatterWorldMapContainer" />
    </template>
    ·····
    <style scoped>
    #ScatterWorldMapContainer {
      width: 100%;
      height: calc(100% - 56px);
      justify-content: center;
      position: relative;
    }
    </style>
    
    <script setup lang="ts">
    import { ref, onUnmounted, defineEmits } from 'vue';
    import { ECharts } from 'echarts';
    // 调取接口返回的散点数据,通过父组件进行传递数据格式如下图
    const props = defineProps({
      countryData: {
        type: Array,
        default: () => [],
      },
      provinceData: {
        type: Array,
        default: () => [],
      },
      cityData: {
        type: Array,
        default: () => [],
      },
    });
    
    与后端接口协调数据或者自己写mock假数据格式在这里插入图片描述
参数
const scatterChart = ref<ECharts | null>(null);
// echarts对象
const mapStack = ref<any[]>([]);
// 坐标系数组
onUnmounted(() => {
  scatterChart.value?.dispose();
});
// 销毁
defineExpose({
  initContainer, // 渲染函数
});
// 暴露出去便于父组件接口返回后ref渲染 或者直接initContainer()

2、渲染实现

const initContainer = async () => {
 // 导入echarts
 const echarts = await import('echarts');
 // 导入世界地图
 const worldGeoJson = (await import('./worldGeoJson')).default;
 // dom绑定
 scatterChart.value = echarts.init((document as any).getElementById('ScatterWorldMapContainer'));
 // echarts的事件监听
 bindOnClickChart(); // 绑定自定义点击事件 用于双击进入中国地图坐标系
 bindOnContextmenuChart(); // 绑定自定义右击事件 用于返回世界地图坐标系
 bindOncontextHover(); // 绑定自定义hover事件 用于实现选中散点高亮地图所在区域

 const mapName = 'world'; // 起始显示世界地图
 scole.value = 10; //  控制散点大小的参数
 let maxCount = 0; // 数据筛选 用于筛选大于0的数据
 const countryDataMap: any = props.countryData.reduce((countryDataMap: any, item: any) => {
   countryDataMap.set(item.code, item.count);
   if (item.count > maxCount) {
     maxCount = item.count;
   }
   return countryDataMap;
 }, new Map());
 // 针对世界地图下所有国家数据进行筛选 // countryDataMap {'CHN' => 3000, 'AUS' => 2}
 
 const dataList = (worldGeoJson as any).features.reduce((list: any, item: any) => {
   list.push({
     name: item.properties.name,
     value: countryDataMap.get(item.properties.code) ? countryDataMap.get(item.properties.code) : 0,
   });
   return list;
 }, []);
// 根据countryDataMap绘制世界地图数据
 registeRenderMap(mapName, dataList, worldGeoJson, maxCount);
 // mapName:world,数据dataList,坐标worldGeoJson,maxCount:0 
};
const registeRenderMap = async (mapName: any, dataList: any, geoJson: any, maxCount: number) => {
 const echarts = await import('echarts');
 // console.log('geoJson', geoJson)
 if (geoJson) {
   // 注册地图
   echarts.registerMap(mapName, geoJson);
 }
 // 把世界坐标系push到我们的mapStack数组中
 pushStack(mapName, dataList, geoJson, maxCount);
 // 渲染坐标图
 renderMap(mapName, dataList, geoJson, maxCount);
};
// // 把世界坐标系push到我们的mapStack数组中
const pushStack = (mapName: any, dataList: any, geoJson: any, maxCount: number) => {
 mapStack.value.push({
   mapName,
   dataList,
   geoJson,
   maxCount,
 });
};
const renderMap = (mapName: any, dataList: any, geoJson: any, maxCount: number) => {
 // console.log('dataList', dataList)
 const option = {
   geo: { // 地理坐标系组件。地理坐标系组件用于地图的绘制
     map: mapName, // 地图类型
     roam: true, // 是否开启鼠标缩放和平移漫游。默认不开启
     zoom: mapName === 'china' ? 1.2 : 1, // 当前视角的缩放比例。
     itemStyle: { // 地图区域的多边形 图形样式。
       areaColor: '#DEE3E8', // 地图区域的颜色。
       borderColor: '#D9D9D9', // 图形的描边颜色
       borderWidth: 0.6, // 描边线宽。为 0 时无描边。
     },
     scaleLimit: {
       min: 1,
       max: 4,
     },
     label: {
       normal: { // 静态的时候展示样式
         show: false, // 是否显示地图省份得名称
         textStyle: {
           color: '#fff',
           fontSize: 10,
           fontFamily: 'Arial',
         },
       },
       emphasis: { // 动态展示的样式
         color: '#fff',
       },
     },

     emphasis: {
       itemStyle: { // 高亮状态下的多边形和标签样式
         color: '#fff',
         areaColor: '#6ba7ff',
         borderColor: '#fff', // 图形的描边颜色
       },
     },
   },
   tooltip: { // 自定义提示信息
     padding: 0,
     enterable: true,
     transitionDuration: 1,
     textStyle: {
       color: '#000',
       decoration: 'none',
     },
     show: true,
     showContent: true,
     trigger: 'item',
     formatter(params:any) {
       let tipHtml = '';
       tipHtml = `${'<div style="box-sizing: border-box;box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.08), 0px 0px 12px rgba(0, 0, 0, 0.08);border-radius: 4px;width:140px;background: rgba(0, 0, 0, 0.76);font-size: 9px;padding:1px 8px;">'
           + '<div style="width:86%;height:30px;line-height:30px;">'
           + '<span style="color:#fff;font-size:12px;">'}${params.data.name}</span>`
           + '</div>'
           + '<div style="width: 124px;background: rgba(255, 255, 255, 0.1);margin:6px 0;padding:6px">'
           + '<p style="color:#fff;font-size:12px;">'
           + '资产:'
           + `<span style="color:#FFFFFF;margin:0 6px;">${params.data.val}</span>`
           + '</p>'
       '</div>'
       return tipHtml;
     },
   },
   series: [
     {
       name: '风险数量',
       type: 'scatter',
       coordinateSystem: 'geo',
       data: dataList, // series数据内容
       symbolSize(val:any) { // 散点大小控制
         if (val[2] / 10 !== 0) {
           if (scole.value === 20) {
             return val[2] / 10 <= 4 ? 4 : val[2] / 10 > 10 && 10 || val[2] / 10
           }
           return val[2] / 10 <= 8 ? 8 : val[2] / 10 > 20 && 20 || val[2] / 10
         }
         return 0;
       },
       symbolKeepAspect: true,
       encode: {
         value: 2,
       },
       itemStyle: {
         emphasis: {
           label: { show: true },
           borderColor: '#fff', // 图形的描边颜色
           color: {
             type: 'radial',
             x: 0.5,
             y: 0.5,
             r: 0.5,
             colorStops: [{
               offset: 0, color: 'rgba(255, 90, 90, 0.2) ', // 0% 处的颜色
             }, {
               offset: 0.5, color: 'rgba(255, 90, 90, 1) ', // 100% 处的颜色
             }, {
               offset: 1, color: 'rgba(255, 90, 90, 1) ', // 100% 处的颜色
             }],
             global: false, // 缺省为 false
           },
         },
         color: {
           type: 'radial',
           x: 0.5,
           y: 0.5,
           r: 0.5,
           colorStops: [{
             offset: 0, color: '#ff5a5a00', // 0% 处的颜色
           }, {
             offset: 1, color: '#ff5a5a73', // 100% 处的颜色
           }],
           global: false, // 缺省为 false
         },
       },
     },

   ],
 };
 scatterChart.value?.setOption(option as any, true);
};
  1. hover事件

    显示提示时,高亮地图相应区域
    
    const bindOncontextHover = () => {
    	// 鼠标hover监听
      scatterChart.value?.on('mouseover', (params:any) => {
        // console.log(params);
        scatterChart.value?.dispatchAction({
          type: 'highlight',
          // echarts5.0以上支持,5.0以下的需要参考文档,有实现的方式
          geoIndex: params.seriesIndex, // 地图相应区域的Index 与下存在一个即可
          name: params.name,// 地图相应区域的名称 与上存在一个即可
        });
      });
      scatterChart.value?.on('mouseout', (params:any) => {
        // console.log(params);
        // 鼠标离开取消高亮
        scatterChart.value?.dispatchAction({
          type: 'downplay',
          // 用 index 或 id 或 name 来指定 geo 组件。
          // 可以用数组指定多个 geo 组件。
          geoIndex: params.seriesIndex,
          name: params.name,
        });
      });
    }
    
  2. 点击事件进入中国地图

    const bindOnClickChart = async () => {
    // 导入中国省份坐标系
      const chinaGeoJson = (await import('./chinaGeoJson')).default;
      // 监听echarts双击事件
      scatterChart.value?.on('dblclick', (params: any) => {
        if (params.name === '中国大陆') {
          scole.value = 10 // 散点大小控制
          // 数据操作
          let maxCount = 0;
          const provinceDataMap: any = props.provinceData.reduce((provinceDataMap: any, item: any) => {
            provinceDataMap.set(parseInt(item.adcode, 10), item.count);
            if (item.count > maxCount) {
              maxCount = item.count;
            }
            return provinceDataMap;
          }, new Map());
          const provinceDataList = (chinaGeoJson as any).features.reduce((list: any, item: any) => {
            list.push({
              name: item.properties.name,
              value: provinceDataMap.get(item.properties.adcode) ? provinceDataMap.get(item.properties.adcode) : 0,
            });
            return list;
          }, []);
          // 绘制中国地图
          registeRenderMap('china', provinceDataList, chinaGeoJson, maxCount);
          // 同样在registeRenderMap函数中进行了中国地图push到mapStack坐标数组中
        }
      });
    };
    
  3. 右击事件返回世界地图

    用于从中国地图返回世界地图
    上述双击进入中国地图操作后,后我们的坐标系数组mapStack中有两个坐标数据记录
    右击事件删除数组的最后一项重新绘制即可返回世界坐标系
    
    // 绑定自定义右击事件
    const bindOnContextmenuChart = () => {
      // 取消右击默认事件
      const body = document.getElementById('ScatterWorldMapContainer') as HTMLElement;
      body.oncontextmenu = (e) => {
        scole.value = 10
        goBack();
        e.preventDefault();
      };
    };
    
    const goBack = () => {
      // 如果只剩下世界地图 不做操作
      if (mapStack.value.length === 1) {
        return;
      }
      mapStack.value.pop();
      const {
        mapName, dataList, geoJson, maxCount,
      } = mapStack.value.pop();
      // 重新绘制世界坐标系
      registeRenderMap(mapName, dataList, geoJson, maxCount);
    };
    
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要使用 ECharts 绘制地理图,首先需要了解以下几个概念: 1. GeoJSON:一种用于描述地理信息的数据格式,常用于存储地图数据。ECharts 支持读取 GeoJSON 格式的文件。 2. 地图坐标系ECharts 中的地图坐标系包括了“经纬度坐标系”和“其他坐标系”,其中“经纬度坐标系”是最常用的一种,用于绘制世界地图、中国地图等。 3. 热力图:一种用于展示地理数据密度的图表类型,通常用于展示人口密度、气温等数据。 在 ECharts绘制地理图的具体步骤如下: 1. 准备地图数据:可以从第三方地图数据提供商(如百度地图、高德地图等)获取地图数据,也可以自己编写 GeoJSON 格式的地图数据。 2. 配置地图坐标系:在 ECharts 中使用 geo 组件来配置地图坐标系,其中需要指定地图类型、地图数据等信息。 3. 绘制地图:在 ECharts 中使用 series 组件绘制地图,通过设置 series.type 为 'map' 来指定绘制地图类型。 4. 添加数据:可以通过设置 series.data 来添加地理数据,根据数据不同可以绘制不同类型的图表,如散点图、热力图等。 5. 定制样式:可以使用 ECharts 提供的样式配置项来定制地图的样式,如地图颜色、边框、标签等。 下面是一个简单的示例代码,用于绘制中国地图: ```javascript // 引入 echarts 库 import echarts from 'echarts'; // 准备地图数据 const geoJson = require('./china.json'); // 配置地图坐标系 const option = { geo: { map: 'china', roam: true, scaleLimit: { min: 1, max: 10 }, zoom: 1.2, label: { show: true, color: '#000', fontSize: 12 }, itemStyle: { areaColor: '#fff', borderColor: '#999' } }, series: [{ type: 'map', map: 'china', data: [{ name: '北京', value: 100 }, { name: '上海', value: 200 }, { name: '广州', value: 300 }] }] }; // 创建 echarts 实例 const myChart = echarts.init(document.getElementById('main')); // 绘制地图 myChart.setOption(option); ``` 在这个示例中,我们使用了中国地图GeoJSON 数据,并使用了 EChartsgeo 组件来配置地图坐标系,设置了地图的缩放、标签、样式等信息。然后使用 series 组件绘制地图,并添加了一些数据。最后,创建 echarts 实例并调用 setOption 方法来绘制地图

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值