把echarts的饼图放在table的每一个单元格中

把echarts的饼图放在table的每一个单元格中

  • 前言
  • 想法
  • 实现
  • 最后

前言

最近接到了一个新的任务,要求把echarts的饼图放在table的每一个单元格中,饼图显示当前策略盈亏所占比例。

想法

刚开始我就在想或许用render函数很好写出来,将饼图封装在一个组件中,在render函数里使用该组件。

但我的table里的每一项都是从后端传来的,包括表头也是不固定的,会根据想要搜索的日期,生成长度不同的各项。尝试用render函数:

this.symbols[item].render = () => <div class='test'><Chart ref='fetchCharts'></Chart></div>

但是渲染出来饼图的位置不是和它表头与列相对应的。
可能这个render函数我掌握的还不是很行,总之最后回归了原始,使用slot插入的。

实现

1. 先写组件中的静态饼图

先在组件中写一个静态的饼图,不传数据,目的是测试在只写一个option下能否将其显示在各个单元格中,后期再将数据传递到series的data中,就可以实现各个单元格显示同样样式,但数据不同的饼图。

2. 将 组件显示在父组件中

if (this.hideChart === false) {
  for (let item = 1; item < this.symbols.length; item++) {
     // this.symbols[item].render = () => 
this.symbols[item].slot = 'action' } setTimeout(() => { this.$refs.fetchCharts.fetchCharts() }, 500) }

利用for循环,在表头所对应的每一列插入名为 ‘action’ 的slot。
延时调用子组件的函数,是为了先将插槽安置好,再调用子组件,如果在调用子组件前,插槽还未安置好,echarts就会无处安放,导致饼图渲染不出来。

<div v-if="!hideChart">
	<i-table :columns="symbols" :data="data" :loading="loading" :height="tableHeight">
    	<template slot-scope="{ row, index, column}" slot="action">
        	<Chart v-if='data[index][column.title]' ref="fetchCharts"></Chart>
    	</template>
	</i-table>
</div>

在父组件中,利用 v-if ,目的是令没有数据,即不需要饼图的单元格不显示饼图。

3. 为每一个饼图设置不同id
进行完上面的步骤后,发现仅能显示出一个饼图,发现echarts在初始化的时候是需要一个占位的地方,通过获取元素的id,但在子组件中,仅有这一个id,故只能显示一个饼图,所以要为每一个饼图设置不同的id。

<template>
  <div>
    <div class="charts-container"></div>
  </div>
</template>

为容器设置一个类,获取所有类名为 “charts-container” 的 DOM 元素,循环为其添加不同的 id ,并将这些id存到数组中,方便后面使用:

for (let i in chartsContainer) {
  if (chartsContainer[i] === chartsContainer.length) {
    break
  }
  chartsContainer[i].id = 'canvasId' + i
  this.canvasIdArr.push('canvas' + i)
}

4. 将全部饼图显示在页面
设置完id,就可以利用循环数组,分别生成各个echarts饼图,从前的option、init、setOption,均以数组的形式创建,发现全部饼图被显示在页面中。

5. 传递数据
既然已经显示在页面中了,便可以传值了。其他地方不用动,只有data中的value通过父组件传的参数赋值。

父组件:

this.$refs.fetchCharts.fetchCharts(this.chart_data, this.pnArr)

子组件:

data: [
    	{value: this.dataDrawingNum[item], name: '数据'},
        {value: (100 - this.dataDrawingNum[item]).toFixed(2), name: '其他'}
      ],

想让tooltip以百分比的形式显示,可以在tooltip[]里添加:

formatter: function (params) {
  let tip = ''
  tip = params.percent + '%'
  return tip
}

想令饼图在正值时显示绿色,非正值显示红色,可以:

if (this.pnArr[item] > 0) {
  optionArr[item].color = ['#F56C6C', '#409EFF']
} else {
  optionArr[item].color = ['#67C23A', '#409EFF']
}

成功!
把echarts的饼图放在table的每一个单元格中_第1张图片

最后

其实还有一些些的小bug,嘿嘿!这篇文章大概记录了一下思路,其实细节比这个复杂好多,我也不是一下想出来的,都是一点一点捋出来的,代码不是很好看也。。加油!

你可能感兴趣的:(平平无奇的解决问题小能手,#,5.17日开始的项目(vue),项目问题,vue,echarts,iview,i-table,饼图)