Echarts 5实现各种图表

1,068 阅读5分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

对于Echarts,不能说熟练使用吧,但最起码踩了很多坑。在上一篇文章中,重点介绍了世界地图的实现思路,本篇文章就来分别介绍其他图表的使用及部分配置项的使用。

封装组件库

原本我封装的chart组件并没有涵盖太多内容,后期我打算再处理下,争取能做到传值,option只做到写一套,另外loading啊,empty的情况啊,后期都加进来,时间关系,本次不做处理,后期处理后统一来更新。

<template>
  <div id="chart" ref="charts" />
</template>

<script>
import throttle from 'lodash/throttle';
import ResizeObserver from 'resize-observer-polyfill';
// / 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
import * as echarts from 'echarts/core';
// 引入柱状图图表,图表后缀都为 Chart
import { BarChart } from 'echarts/charts';
import 'echarts-wordcloud';
// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent
} from 'echarts/components';
// 标签自动布局,全局过渡动画等特性
import { LabelLayout, UniversalTransition } from 'echarts/features';
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer } from 'echarts/renderers';

// 注册必须的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  BarChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer
]);


export default {
  name: 'Chart',
  props: {
    height: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      chart: null,
      resizeChart: null
    };
  },
  mounted() {
    this.$refs.charts.style.height = this.height;
    this.chart = echarts.init(this.$refs.charts);
    this.resize(document.getElementById('chart'));
  },
  destroyed() {
    window.removeEventListener('resize', this.resizeChart);
    this.chart && this.chart.dispose();
  },
  methods: {
    resize(dom) {
      this.resizeChart = throttle(() => {
        this.chart.resize();
      }, 500);
      this.observer = new ResizeObserver(() => this.resizeChart());
      this.observer.observe(dom);
    },
  }
};
</script>

上述代码就是整个封装的chart组件,在这里主要引入了Echarts必须的配置项,当然我这里是按需引入,所以配置项较多,其实如果用的图表多,完全可以全部引入。 在上述代码中,你应该看到了有三个内容,是不必须的。是的,我来介绍下这三个。

  • ResizeObserver是用来监听图表对应组件容器的大小,从而来自适应;
  • throttle这个api应该很熟悉了,在代码中也能看出来,用在了自适应的过程中;
  • echarts-wordcloud,对啦,就是来实现词云的。

数据拿到了,图表不显示

echarts图表的dom结构会在mounted的时候去挂载,然而这个时候我们的数据还没有请求回来,自然也就无法渲染出来了,我们需要在挂载之前就将数据请求回来,就是将数据请求放在created生命周期中。 或者像我,数据如果是通过组件传值拿到的,那么就可以这样来处理,用 $nextTick方法,让它在下一个事件队列中去渲染。

this.$nextTick(() => {
  this.$refs.pieChart.chart.setOption(this.initOption);
});

词云实现过程中遇到的问题

既然上面提到了,那就先来说一下词云吧。在Echarts的提供的示例中并没有词云,但是他提供了一个库,供我们使用,就是上面提到的echarts-wordcloud,我们只需要装一下,就可以使用啦。 该图标的type设置为:wordCloud即可。 这里有几个配置项来介绍下:

// 字体分布的密集程度
gridSize: 10,
// 字体大小的范围
sizeRange: [12, 20],
// 字体旋转的角度
rotationRange: [0, 0],

上面几个配置项还蛮关键的,因为当时我在实现的时候,容器特别小,词又特别长,以至于返回一条数据,我的容器都放不下,你敢信?当时我还以为出bug了,命名返回了一条数据,我的div中却是空白一片。这可不行啊,查了一番才明白,是放不下,所以空白了。这个时候就可以调节上面几个参数来处理。 另外呢,也是因为我的div太小了,会出现返回十条数据,却展示了六七条的情况,这个怎么处理呢?同样有一个配置项,很管用哦:

drawOutOfBound: true,

就这小小的代码,能够保证返回的数据全部显示哦。

折线图实现的时候,纵坐标表示流量,会出现1M点在下,100K点在上的情况

这种场景不知道有没有小伙伴遇到过?是这样的,我拿到的数据单位是字节,然而我需要根据数值的大小转换为K,或M,或G,进而渲染到图表上。第一次在实现的时候,我是这样处理的:

getTrafficDetail(data) {
  let detail = data / 1000;
  if (detail < 1000) {
    return detail.toFixed(2) + 'K';
  } else if (detail >= 1000 && detail < 1000 * 1000) {
    return (detail / 1000).toFixed(2) + 'M';
  } else if (detail >= 1000 * 1000) {
    return (detail / (1000 * 1000)).toFixed(2) + 'G';
  }
}

上述代码遇到的问题是什么呢?就是上面标题中的问题。因为当我拿到一个数据的时候,不管单位,只管大小,那计算出来有可能是M,有可能是G,而对于折线图的纵坐标来说,他只管你的value值,什么单位,他才不管呢。解决方案就是统一单位,最后是这样处理的:

let unit = '';
  if (detail < 1000) {
    unit = 'K';
  } else if (detail >= 1000 && detail < 1000 * 1000) {
    unit = 'M';
  } else if (detail >= 1000 * 1000) {
    unit = 'G';
  }
getTrafficDetailChart(data, unit) {
  let detail = data / 1000;
  if (unit === 'K') {
    return detail.toFixed(2) + 'K';
  } else if (unit === 'M') {
    return (detail / 1000).toFixed(2) + 'M';
  } else if (unit === 'G') {
    return (detail / (1000 * 1000)).toFixed(2) + 'G';
  }
}

半圆环图是如何实现的

一如往常,我的需求是实现半圆环,好家伙,去官网示例中找,咦,没找到。 好吧,有圆环,那就从圆环上截取吧。 image.png 主要思路是配置项用圆环的配置项,而圆环下面的50%的颜色设置为页面背景色的颜色,在上面的50%上做文章。是不是思路很清晰呢?这个时候只要注意几个点就没问题了:

  • 图例legend:最后一个图例要返回空,否则会显示在页面上;
  • 悬浮tooltip:下半部分要返回空即可;
  • 在处理series.data的时候,一定不要忘记在最后push上name值为空,value值为返回的总total值,这样就能保证上下都是一样大啦;
  • tooltip上若显示百分比,这儿要计算一下,否则算出来的上面部分就会等于50%,而不是100%。

总结,本次开发大概实现了九个图表,其实还遇到了不少问题。但是要相信一点,就能很快解决遇到的问题,那就是想要实现的内容在配置项里面都可以实现。静下来,慢慢去找配置项就好啦。