0


echarts 地图和柱状图结合(在地图上显示柱状图)

如图,需求要做一个在地图上显示柱状图的echarts图,但是百度了半天,发现很少有人发这种例子。这个代码也是借鉴的别人的文章,但需求肯定不完全一致,那我会根据我的需求把代码和注意事项发出来并解释。(如果有人发现了借鉴的那篇,请在评论区发一下链接,我找不到了,谢谢)

话不多说,先上代码

目录:

index.vue文件(也就是组件)

<template>
  <div class="ChinaEcharts">
    <div class="wrap">
      <div id="map" :style="'width:' + Width + ';height:' + Height">
        <div :style="'width:' + Width + ';height:' + Height" ref="myEchart"></div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import tangshan from "./tangshan.json";
import Options from "./optionConfig"; //地图配置
export default {
  name: "ChinaEcharts",
  props: {
    Width: {
      type: String,
      default() {
        return '100%';
      },
    },
    Height: {
      type: String,
      default() {
        return '360px';
      },
    },
    areaData: {
      type: Array,
      default() {
        return [];
      },
    },
    option: {
      type: Object,
      default() {
        return new Options();
      },
    },
    cityConfig: {
      type: Object,
      default() {
        return {};
      },
    },
    areaItems: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      wrap: null, //包裹框
      drawBar: null, // 柱状图
      barWrap: null,
      myChart: null,
      // 地区坐标
      selfAreaItems: {},
      selfAreaData: [],
      selfOption: new Options(),
      barColor: ''
    };
  },
  watch: {
    areaData: {
      deep: true,
      handler: function(newVal,oldVal) {
        this.initEcharts();
      }
    }
  },
  methods: {
    loadMap(mapName, data) {
      if (data) {
        console.log(mapName, data, "mapName, datamapName, data");
        this.echarts.registerMap(mapName, data);
      }
    },
    initEcharts() {
      this.echarts.registerMap("map", tangshan);
      this.selfAreaData = JSON.parse(JSON.stringify(this.areaData));
      this.selfOption = JSON.parse(JSON.stringify(this.option));
      this.myChart = this.echarts.init(this.$refs.myEchart);
      if (this.cityConfig.dataJson) {
        this.loadMap(this.cityConfig.name, this.cityConfig.dataJson);
      }
      this.selfAreaItems = JSON.parse(JSON.stringify(this.areaItems));
      window.onresize = this.myChart.resize;
      this.myChart.setOption(this.selfOption);
      // 拖拽跟缩放重置
      let throttledRenderEachCity = this.throttle(this.renderItems, 0);
      this.myChart.on("geoRoam", throttledRenderEachCity);
      this.renderItems();
    },
    // 缩放和拖拽
    throttle(fn, delay, debounce) {
      let currCall;
      let lastCall = 0;
      let lastExec = 0;
      let timer = null;
      let diff;
      let scope;
      let args;
      delay = delay || 0;
      function exec() {
        lastExec = new Date().getTime();
        timer = null;
        fn.apply(scope, args || []);
      }

      let cb = function () {
        currCall = new Date().getTime();
        scope = this;
        args = arguments;
        diff = currCall - (debounce ? lastCall : lastExec) - delay;

        clearTimeout(timer);

        if (debounce) {
          timer = setTimeout(exec, delay);
        } else {
          if (diff >= 0) {
            exec();
          } else {
            timer = setTimeout(exec, -diff);
          }
        }

        lastCall = currCall;
      };

      return cb;
    },
    // 填充 地图点位
    renderItems() {
      let option = Object.assign(this.selfOption, {
        xAxis: [],
        yAxis: [],
        grid: [],
        series: [],
        tooltip: {
          trigger: "item",
          axisPointer: {
            type: "none",
          },
        },
      });
      this.selfAreaData.forEach((item, idx) => {
        let nodeCoord = this.selfAreaItems[item.areaName];
        let coord = this.myChart.convertToPixel("geo", nodeCoord);
        let itemData = []
        itemData.push(Number(item.value));
        if(item.value >= 0 && item.value<=5) {
          this.barColor = '#58dabd';
        }else if(item.value > 5 && item.value<=10) {
          this.barColor = '#fec018';
        }else if(item.value > 10) {
          this.barColor = '#f75218';
        }
        if (coord) {
          option.xAxis.push({
            id: idx + item.areaName,
            gridId: idx + item.areaName,
            type: "category",
            // name: item.areaName,//是否显示柱状图文字
            nameLocation: "middle",
            nameGap: 3,
            splitLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            axisLabel: {
              show: false,
            },
            axisLine: {
              show: false,
            },
            // data: titleItems,
            z: 100,
          });
          option.yAxis.push({
            id: idx + item.areaName,
            gridId: idx + item.areaName,
            type: "value",
            splitLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            axisLabel: {
              show: false,
            },
            axisLine: {
              show: false,
              lineStyle: {
                color: "red",
              },
            },
            min: 0,
            max: "dataMax",
          });
          option.grid.push({
            id: idx + item.areaName,
            width: 15,
            height: 30,
            left: coord[0] - 15,
            top: coord[1] - 15,
            z: 10,
          });
          option.series.push({
            id: idx + item.areaName,
            type: "bar",
            xAxisId: idx + item.areaName,
            yAxisId: idx + item.areaName,
            barGap: 0,
            barCategoryGap: 0,
            data: itemData,
            barWidth: 8,
            z: 100,
            itemStyle: {
              normal: {
                color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{  
                  // 四个数字分别对应 数组中颜色的开始位置,分别为 右,下,左,上。例如(1,0,0,0 )代表从右边开始渐
                  // 变。offset取值为0~1,0代表开始时的颜色,1代表结束时的颜色,柱子表现为这两种颜色的渐变。
                  offset: 0,
                  color: '#ffffff'
                }, {
                  offset: 1,
                  color: this.barColor
                }]),
              },
              opacity: 0,
              emphasis: {
                label: {
                  show: false,
                },
              },
            },
          });
        }
      });
      this.myChart.setOption(option);
    },
  },
};
</script>

** optionConfig.js文件(这个是地图的配置项)**


export default class Options {
  constructor() {
    return {
      tooltip: {},
      geo: {
        map: "map",
        roam: true,
        label: {
          show: false,
          normal: {
            show: true,
            textStyle: {
              color: "#8483c0",
              fontSize: 12,
            },
          },
          emphasis: {
            show: true,
            textStyle: {
              color: "black",
              fontSize: 12,
            },
          },
        },
        itemStyle: {
          // 普通样式。
          normal: {
            areaColor: '#fffefe',//背景颜色
            borderWidth: 2, //设置外层边框
            borderColor: '#8483c0'
          },
          emphasis: {// 也是选中样式
            areaColor: "#8483c0",
            shadowOffsetX: 0,
            shadowOffsetY: 0,
            shadowBlur: 20,
            borderWidth: 0,
            shadowColor: "rgba(0, 0, 0, 0.5)",
          }
        },
        clickable:false,

      },
      visualMap: {
        type:'piecewise',
        showLabel:true,
        pieces:[
          {min: 10,label:'>10'}, 
          {min: 6, max: 10,label:'5-10'},  
          {min: 0, max: 5,label:'0-5'},   
        ],
        inRange: {
          color: ['#56dabb','#fec52c','#f7551c']
        },
        seriesIndex: 999,
        left:35,
        bottom:35,
        textStyle: {
          color: "#8483c0",
        }
      },
    };
  }
}

tangshan.json文件(可以到下面的链接下载需要的地图json,下载的格式应该是geoJson,改成json文件就行了)

echarts-map最新实时geoJson文件下载_hxkj.vip_HashTang

组件的引入:

import chinaEcharts from '../components/ChinaEcharts/index.vue'
<china-echarts :areaData="areaData" :areaItems="areaItems"></china-echarts>

** areaData 是数组格式是**

areaData: [
     {
        areaName:'路南区',
        value: 9
    },
    {
        areaName:'路北区',
        value: 19
    },
    {
        areaName:'遵化市',
        value: 2
    },
    {
        areaName:'迁西县',
        value: 5
    },
    {
        areaName:'丰南区',
        value: 10
    },
],

areaItems 因为每个柱状图是遍历的 所以这个传入的配置项是地区对应的柱状图坐标(这个坐标可以在json文件找,我图省事就是用的center坐标,如果有更好的方法请告知我谢谢)

代码放完了,接下来改说说注意事项是什么了

** 第一个注意点(最重要!!!):调后台接口有数据但是没有图**

** **我们柱状图的数据肯定是要调后台接口的。但是会发现我们用假的数据,能正常显示柱状图,但是调了后台接口就显示不出来了。在模拟的数据和处理返回的数据格式都一致的情况下。那就是渲染的问题了。

   我们请求是异步的,所以客户端就没等服务端相应完就渲染了。所以会导致柱状图再渲染的时候,你传入的数据还是空的

** 解决办法:**

     用**watch**监听数据变化 在渲染柱状图(我这个是封装的组件,如果是在同一个页面就直接在请求接口的方法里面调用**initEcharts**方法就行了)。用假数据测试,**initEcharts**方法写在mounted里面就行。
watch: {
    areaData: {
      deep: true,
      handler: function(newVal,oldVal) {
        this.initEcharts();
      }
    }
  },

第二个注意点:柱状图渐变色的问题

** 我的需求是根据传入的不同数值,显示不同的颜色,在index**文件里面 **renderItems()**里面是写柱状图配置的。

    在series里面的itemStyle的normal 写color的配置

   **renderItems** **()**里面写对颜色的判断

color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{  
      // 四个数字分别对应 数组中颜色的开始位置,分别为 右,下,左,上。例如(1,0,0,0 )代表从右边开始渐
   // 变。offset取值为0~1,0代表开始时的颜色,1代表结束时的颜色,柱子表现为这两种颜色的渐变。
  offset: 0,
  color: '#ffffff'
 }, {
   offset: 1,
    color: this.barColor
]),

注意:offset 中间也可以加0.5,这样就可以三个颜色过渡了。

第三个注意点:visualMap会覆盖柱状图的渐变色

** ** echarts里面地图的示例配置是visualMap 不是 lengend

导致会覆盖柱状图颜色的罪魁祸首就是seriesIndex,echarts官网说的很清楚了,因为我这块只是为了展示用,不做任何功能,所以就不用关联 设一个不可能的值就行了,这样就不会覆盖改好的柱状图颜色了。

第四个注意点:一个地区渲染多个柱状条和名字

** ** 在index文件中,传入的areaData里面的areaName就是每个柱状图的名字,不过我不需要,需要的把他打开就行了

如果在一个地区渲染多个柱状条的话,itemData也就是areaData里面的value,这是一个数组,如果传入的数组长度是2,那就在一个区域会显示两个柱条,并且有高低变化。

第五个注意点:echarts引入方式

import * as echarts from 'echarts'

不管在哪引入echarts,要用* as的形式,官方推荐用法,直接用import from 可能报echarts undefined的错

补充 :解决每个区域柱状图高度一直问题

** ** 这个问题真的想了很久,甚至想过在数组里面加一个value,然后只显示一个柱条。但没想到咋改。突然茅塞顿开,既然让他给高度不一致,直接设置y轴刻度不就行了。一开始想的是把每组的最大值算出来赋给y轴刻度。然后想了一下不太好,如果数据很多总和加起来就很多了,那少的数据不就几乎看不见了。所以要算每个区域的最大值赋给y轴,话不多说,上代码

    ![](https://img-blog.csdnimg.cn/b7deb7798f69428c9d2a26814d675811.png)

** 在initEcharts方法里面获取最大值**

// 遍历数组获取最大值
for(let i = 0;i<this.selfAreaData.length;i++) {
  if(this.maxValue<this.selfAreaData[i].value) {
    this.maxValue = this.selfAreaData[i].value
   }
}
  **  或者换一种更简便的方法,用reduce函数一行代码**
this.maxValue = this.selfAreaData.reduce((pre, cur) => pre > cur?.value ? pre : cur?.value)

data里面定义一下maxValue

    ![](https://img-blog.csdnimg.cn/71c739e3bd2f496e89f2f83307e25009.png) 

** 在柱状图配置项里面的yAxis里面的max属性设置刻度就搞定了**

最后附效果图(柱条的样式可以根据需要修改)

如有问题,请指出,谢谢!


本文转载自: https://blog.csdn.net/qq_36413409/article/details/127734360
版权归原作者 wisdom-bear 所有, 如有侵权,请联系我们删除。

“echarts 地图和柱状图结合(在地图上显示柱状图)”的评论:

还没有评论