vue3+ts 写echarts 中国地图,且封装echarts

 需要引入二次封装的echarts和在ts文件写的option

<template>
  <div class="contentPage">
    <myEcharts :options="chartOptions" class="myEcharts" id="myEchartsMapId"             
     ref="mapEcharts" />
  </div>
</template>

<script setup name="Index" lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, defineExpose } from 'vue';
import myEcharts from '@/components/MyEcharts';//这是我封装的echarts组件,看个人需求添加,我放在文章最后面
import { chinaMap } from '@/plugins/optoons';

const chartOptions: any = ref({});
let dataList: any = ref([
  {
    name: '南海诸岛',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '北京',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '天津',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '上海',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '重庆',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '河北',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '河南',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '云南',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '辽宁',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '黑龙江',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '湖南',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '安徽',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '山东',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '新疆',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '江苏',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '浙江',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '江西',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '湖北',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '广西',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '甘肃',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '山西',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '内蒙古',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '陕西',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '吉林',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '福建',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '贵州',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '广东',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '青海',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '西藏',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '四川',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '宁夏',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '海南',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '台湾',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '香港',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  },
  {
    name: '澳门',
    value: Math.floor(Math.random() * 100) // 返回 0 至 99 之间的数
  }
]);

let observer: ResizeObserver | null = null;
let resizeTimer: any = null;

const mapEcharts: any = ref();

onMounted(() => {
  initMap();

  observer = new ResizeObserver(handleResize);
  observer.observe(document.getElementById('myEchartsMapId'));
});

const handleResize = () => {
  clearTimeout(resizeTimer);
  resizeTimer = setTimeout(() => {
    mapEcharts.value?.autoResize();
  }, 200);
};

onBeforeUnmount(() => {
  if (observer) {
    observer.disconnect();
  }
});

const initMap = () => {
  chartOptions.value = chinaMap(dataList.value);
};
</script>

<style scoped lang="scss" name="Home">
.contentPage {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  justify-items: center;
  align-items: center;

  .myEcharts {
    width: 100%;
  }
}
</style>

 单独把option写在一个ts文件里

import * as echarts from 'echarts';
import chinaMapJson from '@/plugins/chinaMap.json';

export const chinaMap = (dataList: Array<any>) => {
  echarts.registerMap('china', chinaMapJson);

  const option: object = {
    tooltip: {
      triggerOn: 'mousemove', //mousemove、click
      borderColor: 'rgba(65, 119, 254,  1)', //边框颜色
      alwaysShowContent: false,
      backgroundColor: 'rgba(238, 241, 255, 1)', //背景颜色
      textStyle: {
        fontSize: 14,
        color: 'rgba(51, 71, 93, 1)'
      },
      formatter: (params: any) => {
        return params.name + ': ' + params.value + '万人';
      }
    },
    geo: {
      map: 'china',
      roam: true, //是否允许缩放,拖拽
      zoom: 1.2, //初始化大小
      //缩放大小限制
      scaleLimit: {
        min: 1, //最小
        max: 10 //最大
      },
      label: {
        normal: {
          show: true,
          fontSize: '14',
          color: 'rgba(0,0,0,0.7)'
        }
      },
      //设置中心点
      center: [104.97, 35.71],
      // 省份地图添加背景
      itemStyle: {
        areaColor: '#bcc5ee',
        borderColor: 'rgba(0, 0, 0, 0.2)',
        borderWidth: 1
      },
      emphasis: {
        areaColor: '#FF6347',
        shadowOffsetX: 0,
        shadowOffsetY: 0,
        borderWidth: 0
      }
    },

    // visualMap: {
    //   show: true,
    //   left: 40,
    //   bottom: 50,
    //   showLabel: true,
    //   textStyle: {
    //     color: 'rgba(0,0,0,0.7)', //图例文字的样式
    //     fontSize: 14 //字体大小
    //   },
    //   pieces: [
    //     {
    //       gte: 15,
    //       label: '15万人以上',
    //       color: '#009dff'
    //     },
    //     {
    //       gte: 10,
    //       lt: 15,
    //       label: '10-15万人',
    //       color: '#3c57ce'
    //     },
    //     {
    //       gte: 5,
    //       lt: 10,
    //       label: '5-10万人',
    //       color: '#6f83db'
    //     },
    //     {
    //       gte: 1,
    //       lt: 5,
    //       label: '1-5万人',
    //       color: '#9face7'
    //     },
    //     {
    //       lt: 1,
    //       label: '1万人以下',
    //       color: '#bcc5ee'
    //     }
    //   ]
    // },
    visualMap: {
      type: 'continuous',
      text: ['', ''],
      showLabel: true,
      left: '50',
      min: 0,
      max: 100,
      inRange: {
        color: ['#edfbfb', '#b7d6f3', '#40a9ed', '#3598c1', '#215096']
      },
      splitNumber: 0
    },
    series: [
      {
        name: '中国地图',
        type: 'map',
        geoIndex: 0,
        data: dataList
      }
    ]
  };
  return option;
};

中国地图json,也可去阿里云地理网站进行下载(重要!!!)

DataV.GeoAtlas地理小工具系列 (aliyun.com)

echarts 中国地图json文件-CSDN博客

 二次封装echarts组件

<template>
  <div ref="chartRef" class="chart-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, defineExpose } from 'vue';
import * as echarts from 'echarts';

// 定义 Props 类型
interface ChartProps {
  options: EChartsOption;
  // 可以添加其他 props 如:autoResize, theme 等
}

const props = withDefaults(defineProps<ChartProps>(), {
  options: () => ({} as EChartsOption)
});

const chartRef = ref<HTMLDivElement | null>(null);
let chartInstance: echarts.ECharts | null = null;

// 初始化 ECharts
onMounted(() => {
  if (chartRef.value) {
    chartInstance = echarts.init(chartRef.value);
    chartInstance.setOption(props.options);

    // 如果需要,添加窗口大小变化时的响应式处理
    window.addEventListener('resize', () => {
      chartInstance?.resize();
    });
  }
});

// 监听 options 的变化并更新图表
watch(
  () => props.options,
  (newOptions) => {
    if (chartInstance) {
      chartInstance.setOption(newOptions);
    }
  },
  { deep: true }
);

// 清理
onBeforeUnmount(() => {
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
    window.removeEventListener('resize', () => chartInstance?.resize());
  }
});

// 提供 API
defineExpose({
  // 例如:提供一个方法来刷新图表
  refreshChart(newOptions: EChartsOption) {
    if (chartInstance) {
      chartInstance.setOption(newOptions);
    }
  },
  // 获取 ECharts 实例(谨慎使用,可能会破坏封装性)
  getChartInstance() {
    return chartInstance;
  },
  //自适应容器宽度高度
  autoResize() {
    chartInstance?.resize();
  }
});
</script>

<style scoped>
.chart-container {
  width: 100%;
  height: 100%;
}
</style>

最后效果展示

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一路向北. 

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值