echarts地图绘制代码留用
地图绘制
- 创建echarts[画布组件],组件需确保引入绘制地图相关模块、要绘制的对应区域数据信息
- 请求疫情数据,处理为需要绘制的疫情数据,传入画布组件
引入地图区域数据有两种方式,以引入湖北数据为例:
- 使用 echarts自带的区域数据: require(echarts/map/js/province/hubei.js)
- 使用本地的区域数据(echarts地图信息不太规范建议使用本地数据)- 创建本地文件 src/data/hubei.js
- ECharts.registerMap('湖北省', require(@/data/hubei.js- ))
- hubei.js:module.exports = {
 type: "FeatureCollection",
 features: [
 {
 id: "230100",
 type: "Feature",
 geometry: {
 type: "Polygon",
 coordinates: [],
 encodeOffsets: [[128780, 46625]]
 },
 properties: {
 cp: [127.442464, 45.756967], // 控制在地图上 ’哈尔滨‘ 所展示的位置,代表经纬度
 name: "哈尔滨",
 childNum: 1
 }
 },
 ...
 ],
 UTF8Encoding: true
 
- 创建本地文件 
可能遇到的问题
如何拿到区域数据的json信息?
- 在 node_modules\echarts\map\json\province找到对应省份的数据
- GitHub找到对应的json数据
如何定制地图某个城市的name样式(浙江省单独定制杭州市的样式)
参考[天津版定制地图],131行,formatter方法返回 {richKey|name},name表示在地图展示的城市名,richKey匹配formatter同级的rich对应key的内容样式
如果要将城市名称竖排,return城市名称以 \n 连接换行即可
地图展示色块与传入的数据不匹配?
echarts 以区域数据的 name 字段匹配传入的绘制数据,绘制数据name可能是 杭州,而区域绘制数据 name 是 杭州市 导致无法正确绘制
解决方式:
- 使用本地地图数据,将城市的name改为与接口匹配的name
- 地图组件,将传入的疫情数据的name改为与地图数据匹配的name
- 将引入的地图数据遍历处理,重新使用 ECharts.registerMap(city, json)订阅
示例
<template>
  <div class="tianjin-map-wrapper">
    <v-chart :options="options" autoresize />
  </div>
</template>
<script type="text/ecmascript-6">
import ECharts from 'vue-echarts'
import 'echarts/lib/chart/map'
import 'echarts/lib/component/geo'
import 'echarts/lib/component/visualMap'
import 'echarts/lib/component/title'
import 'echarts/lib/component/tooltip'
const mapData = require('@/data/tianjin')
ECharts.registerMap('天津', mapData)
const cityArr = [
  '和平区',
  '河东区',
  '河西区',
  '南开区',
  '红桥区',
  '河北区'
]
export default {
  components: {
    'v-chart': ECharts
  },
  props: {
    optionData: {
      default: function () {
        return []
      }
    }
  },
  data () {
    return {
      cityArr,
      options: {}
    }
  },
  mounted () {
    this.draw()
  },
  methods: {
    draw () {
      let rem = document.documentElement.clientWidth / 375
      ;(rem > 1.5) && (rem = 1.5)
      const getDprUnit = fz => fz * rem
      const optionData = this.optionData
      this.options = {
        title: {
          text: '天津疫情',
          textStyle: {
            color: '#2B313D',
            fontSize: getDprUnit(18)
          },
          left: '65%',
          top: '12%',
          subtext: '分布图',
          subtextStyle: {
            color: '#5E616B',
            fontSize: getDprUnit(12)
          }
        },
        tooltip: {
          transitionDuration: 0,
          triggerOn: 'mousemove',
          formatter: function ({value, name, data}) {
            const { cureCnt, suspectCnt, dieCnt } = data || {}
            if (value > 0) {
              return `${name}<br />确诊:${value}例<br />治愈:${cureCnt}例<br />死亡:${dieCnt}例`
            } else if (suspectCnt > 0) {
              return `${name}<br />疑似:${suspectCnt}例`
            }
            return `${name}:-`
          }
        },
        visualMap: {
          min: 0,
          max: 5000,
          align: 'left',
          left: '65%',
          bottom: '7%',
          showLabel: true,
          hoverLink: false, // 禁用hover
          textStyle: {
            color: '#5E616B',
            fontSize: getDprUnit(12)
          },
          itemWidth: getDprUnit(15),
          itemHeight: getDprUnit(10),
          textGap: getDprUnit(7), // 文本间距
          itemGap: getDprUnit(8), // 图元间距 色块
          pieces: [
            {
              gte: 11,
              label: '大于10人',
              symbol: 'roundRect',
              color: '#FF695C'
            },
            {
              gte: 5,
              lt: 11,
              label: '5-10人',
              symbol: 'roundRect',
              color: '#FFB8A3'
            }, {
              gte: 1,
              lt: 5,
              label: '1-4人',
              symbol: 'roundRect',
              color: '#FFDEBF'
            }, {
              value: 0,
              symbol: 'image://https://kano.guahao.cn/xbM261010333',
              label: '0',
              color: '#FFF'
            }
          ],
          show: true
        },
        geo: {
          type: 'map',
          map: '天津',
          left: '5%',
          label: {
            roam: false,
            zoom: 0.9,
            normal: {
              show: true,
              fontSize: getDprUnit(10),
              // position: 'inside',
              color: '#000',
              align: 'center',
              formatter: function ({name}) {
                let index = cityArr.findIndex(v => name === v)
                const getLabel = name => {
                  if (name.endsWith('新区')) {
                    return name.substr(name, name.length - 2)
                  }
                  if ((name.endsWith('县') || name.endsWith('区'))) {
                    return name.substr(name, name.length - 1)
                  }
                  return name
                }
                const label = index === -1 ? getLabel(name) : ++index
                return `{${typeof label === 'number' ? 'small' : 'default'}|${label}}`
              },
              rich: {
                'small': {fontSize: getDprUnit(6)}
                // 'small': {'color': 'blue', fontSize: getDprUnit(6)}
              }
            }
          },
          itemStyle: {
            normal: {
              color: '#fff',
              borderColor: '#231916'
            },
            emphasis: {
              label: {
                color: '#fff'
              },
              areaColor: '#FFF588',
              borderWidth: 0
            }
          }
        },
        series: [{
          // name: '确诊病例',
          type: 'map',
          geoIndex: 0,
          data: optionData
        }]
      }
    }
  }
}
</script>
<style lang="less" rel="stylesheet/less">
@r: 16/375rem;
@prefix: tianjin-map;
.@{prefix}-wrapper {
  overflow: hidden;
  margin: 0 auto;
  position: relative;
  width: 350 * @r;
  height: 380 * @r;
  color: #000;
  background-size: 128 * @r 263 * @r;
  .m-tips {
    position: absolute;
    left: 66%;
    top: 28%;
    font-size: 12 * @r;
  }
  .echarts {
    width: 100%;
    height: 100%;
  }
}
</style>