echarts踩坑

734 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

本文从工作中摘取比较有典型性的图表来展示echarts踩坑过程。

堆叠柱状图

有时候,我们不仅希望知道不同系列各自的数值,还希望知道它们之和的变化,这时候通常使用堆积柱状图图来表现。顾名思义,堆积柱状图就是一个系列的数值堆积在另一个系列上,因而从他们的高度总和就能表达总量的变化。

使用 EChart 实现堆积折线图的方法非常简单,只需要给一个系列的 stack 值设置一个字符串类型的值,这一个值表示该系列堆积的类别。也就是说,拥有同样 stack 值的系列将堆积在一组。

option = {
  xAxis: {
    data: ['A', 'B', 'C', 'D', 'E']
  },
  yAxis: {},
  series: [
    {
      data: [10, 22, 28, 43, 49],
      type: 'bar',
      stack: 'x'
    },
    {
      data: [5, 4, 3, 5, 10],
      type: 'bar',
      stack: 'x'
    }
  ]
};

image.png

平滑的面积图

要做出下面的这个图有几点需要注意:

  • 图形完全撑满整个区域
  • 整个坐标系占满整个区域
  • 隐藏坐标轴
  • 去掉图形上面的点和线 image.png
getOptions() {
  return {
    xAxis: {
      type: 'category',
      show: false,
      // 距离x轴两侧是有个距离,如果要做极限拉伸必须设置为false
      boundaryGap: false
    },
    yAxis: {
      show: false
    },
    series: [
      {
        type: 'line',
        data: [123, 234, 422, 343, 234, 897, 1000, 410, 908, 100, 200],
        // 展示面积区域
        areaStyle: {
          color: 'purple'
        },
        // 线条变的平滑
        smooth: true,
        // 去掉线条
        lineStyle: {
          width: 0
        },
        // 去掉点
        itemStyle: {
          opacity: 0
        }
      }
    ],
    // 定位:让坐标系占满整个空间
    grid: {
      left: 0,
      right: 0,
      top: 0,
      bottom: 0
    }
  }
}

自定义图表

image.png 我们现在来一步一步的实现上面这个图。

x轴和y轴颠倒

首先是把x轴当做y轴,把y轴当做x轴,颠倒过来才能把柱状图横着摆放:

xAxis: { type: 'value' }, 
yAxis: { type: 'category' }

上面的图是一个进度条,就是有一个总数,还有一个当前的进度,是两条数据,所以应该是两条柱状图:

image.png

series: [ 
    { type: 'bar', data: [200], barWidth: 10 }, 
    { type: 'bar', data: [250], barWidth: 10 }, 
]

最后利用stack属性把柱状图进行叠加:

series: [
  {
    type: 'bar',
    // 让系列进行重合
    stack: '总量',
    data: [200],
    barWidth: 10,
    itemStyle: {
      color: '#45c946'
    }
  },
  {
    type: 'bar',
    stack: '总量',
    data: [250],
    itemStyle: {
      color: '#eee'
    }
  }
]

自定义两个小三角

两个小三角,它们是根据数据进行位置移动的,那如何自定义绘图呢?

自定义绘图就是自定义一个系列, 也就是往series里面加一个对象,这个对象就是自定义的图形。

{
  // type是custom表示是自定义的,
  type: 'custom',
  // 因为也要和上面的bar进行叠加,所以设置stact
  stack: '总量',
  // 这个数据一定要和进度数据保持一致
  data: [100],
  renderItem: (params, api) => {
    const value = api.value(0)
    // 就是自定义的图形放在哪个地方
    const endPoint = api.coord([value, 0])

    return {
      // 返回一组自定义的图形
      type: 'group',
      position: endPoint,
      children: [
        {
          type: 'path',
          shape: {
          // 这个就是svg,可以到iconfont里面找个图标,然后复制它的svg里面d属性的值即可
            d: 'M1024 255.996 511.971 767.909 0 255.996 1024 255.996z',
            // x, y表示相对于父节点进行偏移,就是微调放在哪个地方
            x: -5,
            y: -20,
            // 设置图形的宽高
            width: 10,
            height: 10,
            // 我们定义了图形的宽高,但是svg图形自己也有宽高,
            // 为了让svg图形的宽高缩放到我们定义的宽高,那么就需要设置layout
            layout: 'cover'
          },
          style: {
            fill: '#45c946'
          }
        },
        {
          type: 'path',
          shape: {
            d: 'M0 767.909l512.029-511.913L1024 767.909 0 767.909z',
            x: -5,
            y: 10,
            width: 10,
            height: 10,
            layout: 'cover'
          },
          style: {
            fill: '#45c946'
          }
        }
      ]
    }
  }
}

如何画一个比较复杂的饼图

image.png

标题

标题有两个标题:

  • 品类分布
  • 累计订单量,320为副标题
title: [
  {
    text: `品类分布`,
    textStyle: {
      fontSize: 14,
      color: '#666'
    },
    // 设置标题位置
    left: 20,
    top: 20
  },
  {
    text: '累计订单量',
    subtext: '320',
    // 通过left top进行位置的迁移
    left: '34.5%',
    top: '42.5%',
    // 文本水平居中
    textAlign: 'center',
    textStyle: {
      fontSize: 14,
      color: '#999'
    },
    subtextStyle: {
      fontSize: 28,
      color: '#333'
    }
  }
],

圆环

// 数据
chartData = [
    {
        legendname: axis[index],
        value: item,
        percent,
        itemStyle: {
           color: colors[index]
        },
        name: `${axis[index]} | ${percent}`
    }
]
{
  // 最好在每个系列中写一个name,因为这个name会展示到tooltip上。  
  name: '品类分布',
  type: 'pie',
  data: chartData,
  label: {
    show: true,
    position: 'outter',
    formatter: function(params) {
      return params.data.legendname
    }
  },
  // 圆心的位置,房子是宽度的35% 50%的位置,设置了圆心的位置相当于设置了图标的位置,因为饼图就是一个圆,圆心的位置决定了图的位置
  center: ['35%', '50%'],
  // 第一个参数是内半径,第二个参数是外半径,60%指的是整个宽高中最小的那个的60%作为直径, 默认是[0, 75%]
  radius: ['45%', '60%'],
  // 折线
  labelLine: {
    length: 15,
    length2: 5,
    smooth: true
  },
  // 数据排列顺序  顺时针  逆时针
  clockwise: true,
  // 给每个数据块加上一个border,并设置为白色,那么块和块之间就相当于有个空白
  itemStyle: {
    borderWidth: 4,
    borderColor: '#fff'
  }
}

legend

legend: {
  type: 'scroll',
  // 排列方式是垂直的
  orient: 'vertical',
  // 整个legend的高度,如果高度不够,那么就可以scroll
  height: 250,
  // 设置定位
  left: '70%',
  // 整个画布垂直居中
  top: 'middle',
  textStyle: {
    color: '#8c8c8c'
  }
},

tooltip

// 必须在数据中有name属性
tooltip: {
  trigger: 'item',
  formatter: function(params) {
    const str =
      params.seriesName +
      '<br />' +
      params.marker +
      params.data.legendname +
      '<br />' +
      '数量:' +
      params.data.value +
      '<br />' +
      '占比:' +
      params.data.percent
    return str
  }
}

echarts插件:水球图

对于一些比较复杂的图标,我们也没有必要重新画,npm上有很多其他开发者创建的图标,我们可以拿来直接使用,现在以水球图为例来介绍如何使用echarts。

image.png

npm install echarts-liquidfill
import 'echarts-liquidfill'

series: [
  {
    type: 'liquidFill',
    data: [percent],
    color: [this.getColor(newValue)],
    // 振幅8px
    amplitude: 8,
    radius: '80%',
    name: '用户月同比增长',
    label: {
      position: ['50%', '50%'],
      fontSize: 24,
      color: '#999',
      fontWeight: 'normal',
      formatter: v => {
        return `${(v.value * 100).toFixed(2)}%`
      }
    },
    backgroundStyle: {
      color: '#fff'
    },
    itemStyle: {
      shadowBlur: 0,
      shadowColor: '#fff'
    },
    outline: {
      show: true,
      // 内外边框的边距
      borderDistance: 0,
      itemStyle: {
        color: 'none',
        borderColor: '#aaa4a4',
        borderWidth: 1,
        shadowBlur: 0,
        shadowColor: '#fff'
      }
    }
  }
]