echarts实现复合饼图

Echart 复合饼图

要实现如Excel中一样的复合饼图,但发现echarts中并没有相关样例,故根据配置项自行实现

实现思路

  1. 利用echarts中的嵌套环形图进行修改
    在这里插入图片描述
    1.1. 将中间内圆进行平移,构成复合饼图的详细子图,通过media 属性实现
media: [
    {
      query: { minAspectRatio: 1 },
      option: {
        series: [
          { center: ['70%', '50%'] },
          { center: ['30%', '50%'] },
        ]
      }
    }
  ],

实现效果:
在这里插入图片描述
2. 接下来就是要为右边的圆以及左边对应的扇形增加连线,这里用到的markline属性,可以在图中增加自定义的线条.
线的起点在左边扇形边界,线的终点在圆的边上。
因为比较懒,懒得计算,所以右边圆上的终点直接写死了。
所以接下来的重点在于获取到左边扇形的上下边界坐标点:

  • 首先需要获取到环形图的属性,需要在图初次完成渲染时获取到图的信息,找到环形图的_itemLayouts属性,该属性拥有每个扇形圆心坐标,半径值,开始角度,结束角度
  • 根据获得的圆心坐标(cx , cy),半径值(r),开始角度(startAngle),结束角度 (endAngle)计算扇形的边界坐标,然后更新markLine的起始点就可以得到从扇形到圆的连线
    • 计算方式:
      • 开始边界x坐标(x1)= 圆心x坐标 + cos(开始角度) * 半径值
      • 开始边界y坐标(y1)= 圆心y坐标 + sin(开始角度) * 半径值
      • 结束边界x坐标(x2)= 圆心x坐标 + cos(结束角度) * 半径值
      • 结束边界y坐标(y2)= 圆心y坐标 + sin(结束角度) * 半径值
    • 得到(x1, y1),(x2, y2)之后,将值以及之前定好的终点圆的边界坐标写到配置项markLine中,就可以得到复合饼图
  1. 最终效果
    在这里插入图片描述

代码(可复制到codeSandbox中运行)

import "./styles.css";
import React, {useRef, useMemo, useEffect, useState} from 'react';
import ReactEcharts from 'echarts-for-react';

export default function App() {
  const [chartView, setChartView] = useState(null);
  const myCharts = useRef(null);

  useEffect(()=>{
    window.addEventListener('resize', chartResize);
    return () =>{window.removeEventListener('resize', chartResize);}
  }, [])

  const chartResize = () => {
    setChartView(null);
    myCharts && myCharts.current.getEchartsInstance().resize();
  }

  const chartOptions = useMemo(() => {
    console.log('111',chartView)
    let changePos = false;
    let pos = {};
    if (chartView) {
      changePos = true;
      let tmp = chartView[1]._data._itemLayouts[0];
      pos.startTop = {x: tmp.cx + Math.cos(tmp.startAngle) * tmp.r, y: tmp.cy + Math.sin(tmp.startAngle) * tmp.r}
      pos.startBootom = {x: tmp.cx + Math.cos(tmp.endAngle) * tmp.r, y: tmp.cy + Math.sin(tmp.endAngle) * tmp.r} 
    }
    return {
      tooltip: {
        trigger: 'item',
        formatter: '{a} <br/>{b}: {c} ({d}%)'
      },
      legend: {
        data: [
          'Direct',
          'Marketing',
          'Search Engine',
          'Email',
          'Baidu',
        ]
      },
      series: [
        {
          name: 'Access From',
          type: 'pie',
          selectedMode: 'single',
          radius: [0, '30%'],
          label: {
            show: false,
            position: 'inner',
            fontSize: 14
          },
          labelLine: {
            show: false
          },
          data: [
            { value: 1548, name: 'Search Engine' },
            { value: 775, name: 'Direct' },
            { value: 679, name: 'Marketing' }
          ]
        },
        {
          name: 'Access From',
          type: 'pie',
          radius: ['45%', '60%'],
          label: {
            show: false
          },
          labelLine: {
            length: 30
          },
          startAngle: 60,
          data: [
            { value: 1048, name: 'Baidu' },
            { value: 2046, name: 'Email' },
          ],
          markLine:{
            silent: true,
            symbol: 'none',
            data: [
              [
                {x: changePos ? pos.startTop.x : '30%', y: changePos ? pos.startTop.y :47},
                {x: '70%', y: 84}
              ],
              [
                {x: changePos ? pos.startBootom.x :'30%', y: changePos ? pos.startBootom.y :193},
                {x: '70%', y: 157}
              ]
            ]
          }
        }
      ],
      media: [
        {
          query: { minAspectRatio: 1 },
          option: {
            series: [{ center: ['70%', '50%'] }, { center: ['30%', '50%'] }]
          }
        }
      ]
    }
  }, [chartView])

  const onChartReady = ($event) => {
    console.log($event._chartsViews)
    if (!chartView) {
      setChartView($event._chartsViews)
    }
  }

  return (
    <div className="App">
      <ReactEcharts 
        ref={myCharts}
        style={{height: 240, width: '100%'}} 
        opts={{renderer: 'svg'}} 
        option={chartOptions} 
        onChartReady={(event)=>{onChartReady(event)}}
        // 需要加onEvents,不然onChartReady不生效
        onEvents={{resize: ()=>{console.log('resize')}}}
      />
    </div>
  );
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Vue中使用Echarts实现复合饼图,可以参考以下步骤: 1. 首先,确保你已经安装了Echarts和Vue的相关依赖包。你可以使用npm或yarn来安装它们。 2. 在Vue组件中引入Echarts,并在data属性中定义需要展示的数据。你可以参考结合之前提到的两篇文章,根据你的需求来定义数据的结构。 3. 在Vue组件的mounted钩子函数中,通过获取DOM元素的方式创建一个Echarts实例,并传入需要展示的DOM元素和数据。 4. 在Echarts实例中,使用series属性来定义复合饼图的主要饼图和辅助饼图。你可以使用markLine属性来画线并确定起点和终点坐标。 5. 如果需要设置复合饼图的起始角度,你可以使用startAngle属性来计算出合适的角度。 6. 最后,使用Echarts的setOption方法将配置项应用于实例,从而渲染出复合饼图。 下面是一个简单的代码示例,用于演示如何在Vue中使用Echarts实现复合饼图: ``` <template> <div id="chart"></div> </template> <script> import echarts from 'echarts'; export default { mounted() { // 获取DOM元素 const chartContainer = document.getElementById('chart'); // 创建Echarts实例 const chart = echarts.init(chartContainer); // 定义数据 const data = [ { value: 335, name: '饼图1' }, { value: 310, name: '饼图2' }, { value: 234, name: '饼图3' }, { value: 135, name: '饼图4' }, { value: 1548, name: '饼图5' } ]; // 设置配置项 const option = { series: [ { type: 'pie', radius: '50%', data: data }, { type: 'pie', radius: ['60%', '80%'], data: data } ], // 其他配置项... }; // 将配置项应用于实例 chart.setOption(option); } }; </script> ``` 请根据你的需求和数据结构进行适当的修改,以实现你想要的复合饼图效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值