echarts地图的简单使用

文章说明

主要介绍echarts地图组件的简单使用,记录为文章,供后续查阅使用

目前只是简单的示例,然后还存在着一些小bug,主要是首个Legend的点击会导致颜色全部不展示的问题,以及世界地图的区域展示有一些小问题,等待后续完善

核心源码

地图绘制组件

<script setup>
import * as echarts from "echarts";
import china from "@/assets/china.json";
import world from "@/assets/world.json";
import {onBeforeMount, onMounted, reactive} from "vue";
import {getAreaList} from "@/assets/getAreaList";
import {calculateColor} from "@/util";

const data = reactive({
  mapName: "china",
  chinaAreaList: [],
  selectedChinaAreaList: [],
  worldAreaList: [],
  selectedWorldAreaList: [],
});

onBeforeMount(() => {
  const {chinaAreaList, worldAreaList} = getAreaList();
  data.chinaAreaList = chinaAreaList;
  data.worldAreaList = worldAreaList;
});

const mapList = [
  {
    name: "china",
    data: china,
  },
  {
    name: "world",
    data: world,
  }
];

let myChart;

onMounted(() => {
  for (let i = 0; i < mapList.length; i++) {
    echarts.registerMap(mapList[i].name, mapList[i].data);
  }

  const chartDom = document.getElementById("basic-chart");
  myChart = echarts.init(chartDom);
  setOption();

  window.onresize = () => {
    myChart.resize();
  };
});

const mapNameMap = {
  china: "中国地图",
  world: "世界地图",
}

let min = 0;
let max = 10000;
let selectedAreaDataList = [];

function setOption() {
  let selectedAreaList = [];
  if (data.mapName === "china") {
    selectedAreaList = data.selectedChinaAreaList;
  } else if (data.mapName === "world") {
    selectedAreaList = data.selectedWorldAreaList;
  }

  const series = [];
  const colors = [];

  const notSortArray = [];
  for (let i = 0; i < selectedAreaList.length; i++) {
    let selectedAreaData;
    for (let j = 0; j < selectedAreaDataList.length; j++) {
      if (selectedAreaDataList[j].name === selectedAreaList[i]) {
        selectedAreaData = selectedAreaDataList[j];
        break;
      }
    }
    let value;
    if (selectedAreaData) {
      value = selectedAreaData.value;
    } else {
      value = Math.ceil(Math.random() * max);
      selectedAreaDataList.push({
        value: value,
        name: selectedAreaList[i],
      });
    }
    notSortArray.push({
      value: value,
      name: selectedAreaList[i],
    });
  }
  notSortArray.sort(function (o1, o2) {
    return o1.value - o2.value;
  });
  if (!notSortArray.length) {
    colors.push("#ffffff", "#000000");
  }

  const legendNames = [];
  for (let i = 0; i < notSortArray.length; i++) {
    const color = calculateColor(notSortArray[i].value, min, max);
    colors.push(color);
    const seriesItem = {
      name: notSortArray[i].name,
      type: 'map',
      geoIndex: 0,
      data: [
        {
          name: notSortArray[i].name,
          value: notSortArray[i].value
        }
      ],
      color: color,
    };
    series.push(seriesItem);
    legendNames.push(notSortArray[i].name);
  }

  myChart.setOption({
    title: {
      text: mapNameMap[data.mapName],
      left: "center",
    },
    geo: {
      map: data.mapName,
      label: {
        show: false,
      },
    },
    legend: {
      orient: 'vertical',
      bottom: "50px",
      left: '50px',
      itemHeight: 10,
      itemWidth: 30,
      textStyle: {
        fontSize: 12,
        rich: {
          a: {
            verticalAlign: 'middle',
          },
        },
        padding: [2, 0, 0, 0],
      },
      data: legendNames
    },
    series: series,
    visualMap: {
      left: 'right',
      min: min,
      max: max,
      inRange: {
        color: colors
      },
      text: ['High', 'Low'],
      calculable: true
    },
    toolbox: {
      show: true,
      feature: {
        saveAsImage: {
          show: true
        }
      }
    },
  }, true);
}
</script>

<template>
  <div class="container">
    <div style="height: 6rem; display: flex; align-items: center; justify-content: center">
      <el-select v-model="data.mapName" style="width: 10rem; margin-right: 2rem" @change="setOption">
        <el-option label="中国地图" value="china"/>
        <el-option label="世界地图" value="world"/>
      </el-select>
      <el-select v-show="data.mapName === 'china'" v-model="data.selectedChinaAreaList" collapse-tags
                 collapse-tags-tooltip filterable multiple placeholder="请选择地区" style="width: 30rem"
                 @change="setOption">
        <template v-for="item in data.chinaAreaList" :key="item.id">
          <el-option :label="item.name" :value="item.name"/>
        </template>
      </el-select>
      <el-select v-show="data.mapName === 'world'" v-model="data.selectedWorldAreaList" collapse-tags
                 collapse-tags-tooltip filterable multiple placeholder="请选择地区" style="width: 30rem"
                 @change="setOption">
        <template v-for="item in data.worldAreaList" :key="item.id">
          <el-option :label="item.name" :value="item.name"/>
        </template>
      </el-select>
    </div>
    <div style="flex: 1">
      <div id="basic-chart" class="chart"></div>
    </div>
  </div>
</template>

<style lang="scss">
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

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

根据值生成颜色的工具函数

function hsvToRgb(h, s, v) {
    const f = n => {
        const k = (n + h / 60) % 6;
        return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
    };
    return [
        Math.round(f(5) * 255),
        Math.round(f(3) * 255),
        Math.round(f(1) * 255)
    ];
}

export function calculateColor(value, minValue, maxValue) {
    value = Math.max(minValue, Math.min(maxValue, value));

    const factor = (value - minValue) / (maxValue - minValue);
    const hue = (factor * 360) % 360;
    const saturation = 1 - factor;
    const valueV = 1;

    const [r, g, b] = hsvToRgb(hue, saturation, valueV);
    return `rgb(${r}, ${g}, ${b})`;
}

地图数据的下载,可以在该网站下载较为全面的中国地图的数据:DataV.GeoAtlas地理小工具系列

效果展示

中国地图
在这里插入图片描述

世界地图
在这里插入图片描述

源码下载

echarts地图组件的基本使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值