ECharts常用配置项

2021-12-31 08:20:38 浏览数 (1)

前言

ECharts是我们常用的图表控件,功能特别强大,每次使用都要查API比较繁琐,这里就记录开发中常用的配置。

官网:https://echarts.apache.org/handbook/zh/get-started

配置项:https://echarts.apache.org/zh/option.html#title

第三方示例平台:https://www.makeapie.com/explore.html

引用

安装

代码语言:javascript复制
npm install echarts --save

引用

代码语言:javascript复制
import * as echarts from 'echarts';

// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 绘制图表
myChart.setOption({
  title: {
    text: 'ECharts 入门示例'
  },
  tooltip: {},
  xAxis: {
    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
  },
  yAxis: {},
  series: [
    {
      name: '销量',
      type: 'bar',
      data: [5, 20, 36, 10, 10, 20]
    }
  ]
});

设置渲染方式

方式选择

在软硬件环境较好,数据量不大的场景下,两种渲染器都可以适用,并不需要太多纠结。

在环境较差,出现性能问题需要优化的场景下,可以通过试验来确定使用哪种渲染器。

比如有这些经验:

  • 在须要创建很多 ECharts 实例且浏览器易崩溃的情况下(可能是因为 Canvas 数量多导致内存占用超出手机承受能力),可以使用 SVG 渲染器来进行改善。 大略得说,如果图表运行在低端安卓机,或者我们在使用一些特定图表如 水球图 等,SVG 渲染器可能效果更好。
  • 数据量较大(经验判断 > 1k)、较多交互时,建议选择 Canvas 渲染器。

设置代码

代码语言:javascript复制
// 使用 Canvas 渲染器(默认)
var chart = echarts.init(containerDom, null, { renderer: 'canvas' });
// 等价于:
var chart = echarts.init(containerDom);

// 使用 SVG 渲染器
var chart = echarts.init(containerDom, null, { renderer: 'svg' });

数据变化重新渲染

代码语言:javascript复制
chart.setOption(option, notMerge, lazyUpdate);

或者:

代码语言:javascript复制
chart.setOption(option, {
  notMerge: false,
  lazyUpdate: false,
  silent: false
});

参数解释:

  • option 图表的配置项和数据,具体见配置项手册。
  • notMerge 可选,是否不跟之前设置的 option 进行合并,默认为 false,即合并。
  • lazyUpdate 可选,在设置完 option 后是否不立即更新图表,默认为 false,即立即更新。
  • silent 可选,阻止调用 setOption 时抛出事件,默认为 false,即抛出事件。

第二个参数notMerge,将它设置为true即不合并之前的options,使用新的options。

响应容器的大小

代码语言:javascript复制
var myChart = echarts.init(document.getElementById('main'));
window.onresize = function() {
  myChart.resize();
};

注意和VUE结合使用时,一定要等待DOM渲染完毕再调用,否则不生效。

代码语言:javascript复制
async leftbar_click() {
  this.show_left = !this.show_left;
  await this.$nextTick();
  this.echart && this.echart.resize()
}

除了直接调用 resize() 不含参数的形式之外,还可以指定宽度和高度,实现图表大小不等于容器大小的效果。

代码语言:javascript复制
myChart.resize({
  width: 800,
  height: 400
});

VUE封装图表自动缩放

VUE封装组件,让图表随页面变化自动缩放。

resize.js

代码语言:javascript复制
import { debounce } from '@/utils/utils.js'

export default {
  data() {
    return {
      $_mDom: null,
      $_resizeHandler: null
    }
  },
  mounted() {
    this.initListener()
  },
  activated() {
    if (!this.$_resizeHandler) {
      // avoid duplication init
      this.initListener()
    }

    // when keep-alive chart activated, auto resize
    this.resize()
  },
  beforeDestroy() {
    this.destroyListener()
  },
  deactivated() {
    this.destroyListener()
  },
  methods: {
    // use $_ for mixins properties
    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
    $_sidebarResizeHandler(e) {
      if (e.propertyName === 'width') {
        this.$_resizeHandler()
      }
    },
    initListener() {
      this.$_resizeHandler = debounce(() => {
        this.resize()
      }, 100)
      window.addEventListener('resize', this.$_resizeHandler)
      this.$_mDom = document.getElementById('app')
      this.$_mDom && this.$_mDom.addEventListener('transitionend', this.$_sidebarResizeHandler)
    },
    destroyListener() {
      window.removeEventListener('resize', this.$_resizeHandler)
      this.$_resizeHandler = null
      this.$_mDom && this.$_mDom.removeEventListener('transitionend', this.$_sidebarResizeHandler)
    },
    resize() {
      const { chart } = this
      chart && chart.resize()
    }
  }
}

utils.js

代码语言:javascript复制
/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result

  const later = function() {
    // 据上一次触发时间间隔
    const last =  new Date() - timestamp

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function(...args) {
    context = this
    timestamp =  new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在,重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

自定义图表组件中调用

代码语言:javascript复制
import * as echarts from 'echarts'
import resize from "@/components/charts/mixins/resize.js"

export default {
  mixins: [resize],
  data() {
    return {
      chart: null,
    };
  },
}

完整示例

PieRateChart.vue

代码语言:javascript复制
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
  import * as echarts from 'echarts'
  import resize from "@/components/charts/mixins/resize.js"

  export default {
    mixins: [resize],
    props: {
      className: {
        type: String,
        default: "chart",
      },
      width: {
        type: String,
        default: 0,
      },
      height: {
        type: String,
        default: "300px",
      },
      title: {
        type: String,
        default: ''
      },
      mRate: {
        type: String,
        default: () => {
          return "0"
        }
      }
    },
    data() {
      return {
        chart: null,
      };
    },
    watch: {
      mRate: function () {
        this.initChart()
      }
    },
    async mounted() {
      await this.$nextTick();
      this.initChart();
    },
    beforeDestroy() {
      if (!this.chart) {
        return;
      }
      this.chart.dispose();
      this.chart = null;
    },
    methods: {
      initChart() {
        if (!this.chart) {
          this.chart = echarts.init(this.$el);
        }
        let title = this.title;
        let num = parseFloat(this.mRate);
        let mydata = [num, 100 - num];
        let opts = {
          backgroundColor: '#ffffff',
          tooltip: {
            show: true,
          },
          color: ['#3c90f7', '#55bfc0'],
          series: [
            {
              type: 'pie',
              radius: ['60%', '80%'],
              center: ['50%', '50%'],
              hoverAnimation: true,
              data: mydata,
              itemStyle: {
                normal: {
                  borderWidth: 2,
                  borderColor: '#ffffff',
                },
              },
              label: {
                show: false,
              },
            },
          ],
          title: {
            text: num   '%',
            top: '38%',
            textAlign: 'center',
            left: '49%',
            textStyle: {
              color: '#666',
              fontSize: 16,
              fontWeight: '400',
            },
          },
        };
        this.chart.setOption(opts)
      },
    }
  };
</script>

配置项

title

标题组件,包含主标题和副标题。

代码语言:javascript复制
title:{
  show:true,
  text : '',
  textStyle:{
    color: '#333' ,
    fontStyle: 'normal' ,
    fontWeight: 'bolder' ,
    fontFamily: 'sans-serif' ,
    fontSize: 18 ,
    lineHeight ... ,
    width ... ,
    height ... ,
    textBorderColor ... ,
    textBorderWidth ... ,
    textBorderType: 'solid' ,
    textBorderDashOffset: 0 ,
    textShadowColor: 'transparent' ,
    textShadowBlur: 0 ,
    textShadowOffsetX: 0 ,
    textShadowOffsetY: 0 ,
    overflow: 'none' ,
    ellipsis: '...' ,
  },
  subtext: '' ,
  subtextStyle:{},
  zlevel: 0 ,
  z: 2 ,
  left: 'auto' ,
  top: 'auto' ,
  right: 'auto' ,
  bottom: 'auto' ,
}

xAxis/yAxis

直角坐标系 grid 中的 x/y 轴,一般情况下单个 grid 组件最多只能放上下两个 x/y 轴,多于两个 x/y 轴需要通过配置 offset 属性防止同个位置多个x/y 轴的重叠。

代码语言:javascript复制
xAxis:[
  {
    type: "category",
    data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
    axisTick: {
      alignWithLabel: true,
    },
    axisLabel: {
      rotate: 20
    },
    nameLocation: "end",
    name: "%"
  },
]

axisTick:坐标轴刻度相关设置。

axisLabel:坐标轴刻度标签的相关设置。

name:相关的是轴线一侧的文字,如显示单位。

自定义标签内容

代码语言:javascript复制
option = {
  yAxis: {
    axisLabel: {
      formatter: '{value} 元',
      align: 'center'
    }
  }
};

grid

直角坐标系内绘图网格,单个 grid 内最多可以放置上下两个 X 轴,左右两个 Y 轴。可以在网格上绘制折线图,柱状图,散点图(气泡图)。

代码语言:javascript复制
grid: {
  top: 20,
  left: "2%",
  right: "2%",
  bottom: 10,
  containLabel: true,
},

四个方向都可以用百分比和具体数值

containLabeltrue时,left right top bottom width height 决定的是包括了坐标轴标签在内的所有内容所形成的矩形的位置。

legend

图例组件。

图例组件展现了不同系列的标记(symbol),颜色和名字。可以通过点击图例控制哪些系列不显示。

代码语言:javascript复制
legend: {
  type: 'plain',
  orient: 'horizontal',
  data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  bottom: 20,
  align: 'left',
  textStyle: {
    color: '#333',
  },
  itemGap: 10,
  formatter: (name) => {
    let item = null;
    for (const _item of chartData) {
      if (_item.chainName === name) {
        item = _item;
        break;
      }
    }
    if (item) {
      return name   '  '   item.total   '次 '   ((item.successCount * 100) / item.total).toFixed(1)   '%';
    } else {
      return name;
    }

  },
},

其中:

  • itemGap:图例每项之间的间隔。横向布局时为水平间隔,纵向布局时为纵向间隔。

tooltip

悬浮框组件。

代码语言:javascript复制
tooltip: {
  show: true,
  formatter: '{b0}成功率: {c0}%',
},

dataZoom

dataZoom 组件 用于区域缩放,从而能自由关注细节的数据信息,或者概览数据整体,或者去除离群点的影响。

代码语言:javascript复制
dataZoom: {
  right: '2%', //下滑块距离x轴底部的距离
  top: '5%',
  height: '90%', //下滑块手柄的高度调节
  width: 20,
  type: 'slider', //类型,滑动块插件
  show: true, //是否显示下滑块
  yAxisIndex: [0], //选择的y轴
  start: 0, //初始数据显示多少
  end: 100, //初始数据最多显示多少
},

series

折线图

代码语言:javascript复制
series: [
  {
    data: [820, 932, 901, 934, 1290, 1330, 1320],
    type: 'line',
    smooth: true
  }
]

柱状图

代码语言:javascript复制
series: [
  {
    type: 'bar',
    showBackground: false,
    data: valueData,
    barWidth: 16,
    itemStyle: {
      normal: {
        color: '#3c90f7',
        barBorderRadius: [0, 8, 8, 0],
      },
    },
    emphasis: {
      itemStyle: {
        color: specialColor,
      },
    },
  },
],

其中:

  • emphasis:高亮的图形样式和标签样式。

饼图

代码语言:javascript复制
series: [
  {
    type: 'pie',
    radius: ['30%', '45%'],
    center: ['50%', '30%'],
    hoverAnimation: true,
    itemStyle: {
      normal: {
        borderWidth: 2,
        borderColor: '#ffffff',
        label: {
          show: true,
          position: 'outside',
          color: '#ddd',
          formatter: function (params) {
            var percent = 0;
            var total = 0;
            for (var i = 0; i < mydata.length; i  ) {
              total  = mydata[i].value;
            }
            percent = ((params.value / total) * 100).toFixed(0);
            if (params.name !== '') {
              return '名称:'   params.name   'n'   'n'   '比例:'   percent   '%';
            } else {
              return '';
            }
          },
        },
        labelLine: {
          length: 30,
          length2: 100,
          show: true,
          color: '#00ffff',
        },
      },
    },
    label: {
      show: false,
    },
    data: mydata,
    labelLine: {
      show: true,
    },
  },
],

其它

多个图形

代码语言:javascript复制
option = {
  xAxis: [
    { type: 'category', gridIndex: 0, data: ['1月', '2月', '3月'] },
    { type: 'category', gridIndex: 1, data: ['4月', '5月', '6月'], position: 'top' },
  ],
  yAxis: [
    { gridIndex: 0 }, 
    { gridIndex: 1, inverse: true }
  ],
  grid: [
    { bottom: '55%' },
    { top: '55%' }
  ],
  series: [
    // 这几个系列会出现在第一个直角坐标系中
    { type: 'bar', data: [1, 5, 10] },
    { type: 'bar', data: [2, 4, 3] },
    // 这几个系列会出现在第二个直角坐标系中,
    { type: 'line', xAxisIndex: 1, yAxisIndex: 1, data: [2, 5, 8] },
    { type: 'line', xAxisIndex: 1, yAxisIndex: 1, data: [8, 2, 6] },
  ],
};

关键的两个属性:

  • xAxis中的position: 'top'
  • yAxis中的inverse: true

效果如下:

渐变色

代码语言:javascript复制
var specialColor = {
  type: 'linear',
  x: 0,
  y: 0,
  x2: 1,
  y2: 0,
  colorStops: [
    {
      offset: 0,
      color: '#3c90f7', // 0% 处的颜色
    },
    {
      offset: 1,
      color: '#55bfc0', // 100% 处的颜色
    },
  ],
  globalCoord: false, // 缺省为 false
};

option={
  series: [
    {
      type: 'bar',
      showBackground: false,
      data: [1,3,5,2,4],
      barWidth: 16,
      itemStyle: {
        normal: {
          color: '#3c90f7',
          barBorderRadius: [0, 8, 8, 0],
        },
      },
      emphasis: {
        itemStyle: {
          color: specialColor,
        },
      },
    },
  ],
}

0 人点赞