echarts 画饼图,在扇区中 同时设置名称和图片,可以分别点击执行不同方法

文章讲述了在ECharts中实现饼图时,如何在一个扇区中同时显示名称和图片,并且根据图片标志执行不同逻辑处理的过程,分别尝试了rich标签和graphic元素的方法,以及角度计算以确保图片精准定位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.  最近遇到一个奇怪的需求,一个正常的饼图,扇区里面居然不仅要显示名称还要显示图片,最关键的是 点击他两要执行不同的逻辑处理,一开始只是想正常显示个图片那不很简单吗,后来发现事情没有那么简单,因为不是所有的扇区都要显示图片的,他是某几个扇区要显示,研究了很久发现利用rich 可以实现。

下面是第一种方法显示图片很长在上面,如下:

var myChart = echarts.init(document.getElementById('pieLeft'));
 var datas=[
            { value: 100, name: '扇区1',flag:'1' ,},
            { value: 100, name: '扇区2', flag:'0' ,},
            { value: 100, name: '扇区3', flag:'1', },
            { value: 100, name: '扇区4', flag:'0', },
            { value: 100, name: '扇区5', flag:'0', },
            { value: 100, name: '扇区6', flag:'1',},
            { value: 100, name: '扇区7', flag:'1',},
           
]
var colorList=['red','blue','green']
//判断flag为1 的加图片
for(let i=0;i<datas.length;i++){
    if(datas[i].flag== "1"){
                  datas[i].label={
                      formatter: function(params) {
                       //同时显示名称和图片
                          var name = params.name;
                          var index = name.indexOf('MHz');
                          if (index !== -1) {
                              return name.substring(0, index + 3) + '\n' + name.substring(index + 3) + '\n{image|}';
                          } else {
                              return params.name + '\n{image|}';
                          }
                      },
                      textStyle: {
                        color: '#fff',
                        name:"点击",
                        lineHeight: 13,
                        //padding: [20, 5, 5, 0]
                      },
                      rich: {
                        image: {
                          height: 20, // 图片的高度
                          align: 'center',
                          backgroundColor: {
                            image: require('../../../../../public/imgersbor/编辑.png')
                          },
                         
                        },
                      }
                  }
   }else{
      
                 datas[i].label={
                    //只显示名称
                    formatter: function(params) {
                      var name = params.name;
                      var index = name.indexOf('MHz');
                      if (index !== -1) {
                          return name.substring(0, index + 3) + '\n' + 
              name.substring(index + 3);
                      } else {
                          return params.name;
                      }
                    },
                    textStyle: {
                      color: '#376EB9',
                    },
                  }
                }
  }
}
 var option = {
            color : colorList,
           // interact: true,
            title: {
                text: '饼图',
                top: '38%',
                left: 'center',
                textStyle: {
                  color: '#3A70B8',
                  fontSize: 20,
                  fontWeight: 400,
                  width:30,
                  height:30,
                },
            },
            series: [
              {
                name: '',
                type: 'pie',
                radius: ['27%', '60%'],
                center: ['50%', '40%'], // 修改为居中
                avoidLabelOverlap: true,
                label: {
                  normal: {
                    show: true,
                    position: 'inside',
                    textStyle: {
                      align: 'left',
                      baseline: 'middle',
                      fontSize: 12,
                     // color: '#376EB9',//    '#fff',          //'#376EB9',
                      fontWeight: '500',
                      fontFamily:'Microsoft YaHei'
                    },
                  }
                },
                itemStyle: {
                  borderRadius: 10,
                  borderColor: '#fff',
                  borderWidth: 4,   //设置间隙
                },
                labelLine: {
                  show: false
                },
                data: datas,
  
              },
]}   
       
 myChart.setOption(option,true);
 myChart.on('click', function (params){
     console.log(params)
    //执行逻辑
 }

但是这种方法呢只是适合 展示图片,无法做到 点击名称和 图片去执行对应的逻辑操作,我查了大量的资料发现就是不行,echarts官方这么解释的:

在 ECharts 中,点击事件通常是针对图表的元素,如数据点、扇区等。使用 rich 标签来添加图片,那么这个图片本身是不会触发点击事件的。ECharts 的点击事件提供的信息主要是关于被点击的图表元素(如扇区或数据点),并不包括具体的子元素(如标签或图片)。

2.既然这样那我们只能使用第二种方法了,那就是 graphic 元素,我直接添加元素总能获取到吧,于是我试试了发现,果然可以,但是新的问题又来了,什么问题呢?就是 graphic 元素本质是在中心点圆环那里 添加一个图片,而不是在扇区里添加,我们要用他这个方法,只能去改变图片的位置。但是我们如何保证每个扇区图片精准的显示到对应的扇区里呢,他如果错位怎么办,办法总是人想出来的吗,我们只要确定了有哪几个扇区需要显示图片,在获取到对应的扇区位置,把图片放到扇区的中心点不就行了吗。说着挺简单的,但是其中涉及到许多数学的函数 方法还是踩了很多坑。。。代码如下:

 var myChart = echarts.init(document.getElementById('pieLeft'));
        var chartWidth = myChart.getWidth() *0.5; // 获取饼图容器的宽度
        var chartHeight = myChart.getHeight() *0.4; // 获取饼图容器的高度
        console.log('chartWidth',chartWidth,chartHeight)
       
       var datas=[
            { value: 100, name: '扇区1',flag:'1' ,},
            { value: 100, name: '扇区2', flag:'0' ,},
            { value: 100, name: '扇区3', flag:'1', },
            { value: 100, name: '扇区4', flag:'0', },
            { value: 100, name: '扇区5', flag:'0', },
            { value: 100, name: '扇区6', flag:'1',},
            { value: 100, name: '扇区7', flag:'1',},
            // 其他扇区...
        ]
        var graphicElements = [];
        var colorList=['red','blue','green']
        for (var i = 0; i < datas.length; i++) {
          var data = datas[i];
          if (data.flag === '1') {
            var graphicElement = {
              type: 'image',
              id: 'image' + i,
              z: 10,
              style: {
                image: require('../../../../../public/imgersbor/编辑.png'),
                x: 0,
                y: 0,
                width: 20,
                height: 20
              },
            };

            var startAngle = (360 / datas.length) * i;  // 计算每个扇区的起始角度
            var endAngle = (360 / datas.length) * (i + 1);  // 计算每个扇区的结束角度
            var midAngle = (startAngle + endAngle) / 2;  // 计算每个扇区的中间角度
           // console.log('startAngle',startAngle,endAngle,midAngle)
            var radius = chartWidth*0.35;  // 饼图的半径
            var centerX = chartWidth*1;  // 饼图的中心点X轴坐标
            var centerY = chartHeight*1;  // 饼图的中心点Y轴坐标
            var angleInRadians = midAngle * Math.PI / 180;  // 将角度转换为弧度
            var sectorCenterX = centerX + radius * Math.sin(angleInRadians);  // 扇区中心点的X坐标
            var sectorCenterY = centerY - radius * Math.cos(angleInRadians);  // 扇区中心点的Y坐标
            graphicElement.style.x = sectorCenterX;
            graphicElement.style.y = sectorCenterY;
            console.log('x',sectorCenterX,sectorCenterY)
            graphicElements.push(graphicElement);
          }
        }
        console.log('graphicElements',graphicElements)
     
        var option = {
            color : colorList,
           // interact: true,
            title: {
                text: '移动',
                top: '38%',
                left: 'center',
                textStyle: {
                  color: '#3A70B8',
                  fontSize: 20,
                  fontWeight: 400,
                  width:30,
                  height:30,
                },
            },
             graphic: {
                elements:graphicElements
             },
            series: [
              {
                name: '',
                type: 'pie',
                radius: ['27%', '60%'],
                center: ['50%', '40%'], // 修改为居中
                avoidLabelOverlap: true,
                label: {
                  normal: {
                    show: true,
                    position: 'inside',
                    textStyle: {
                      align: 'left',
                      baseline: 'middle',
                      fontSize: 12,
                     // color: '#376EB9',//    '#fff',          //'#376EB9',
                      fontWeight: '500',
                      fontFamily:'Microsoft YaHei'
                    },
                  }
                },
                itemStyle: {
                  borderRadius: 10,
                  borderColor: '#fff',
                  borderWidth: 4,   //设置间隙
                },
                labelLine: {
                  show: false
                },
                data: datas,
  
              },
            ]
        }   

          let that = this   // 保存this指向
          myChart.setOption(option,true);
          //点击事件
          myChart.off("click");
          myChart.on('click', function (params) {
           console.log(params) 
           //可以看到点击图片的类型是 componentType: 'graphic' 
           //可以看到点击名称的类型是 componentType: 'series'        
      }

可以看到 最中间的 角度换算代码是 整个逻辑的核心,最后根据不同的 componentType 类型来确定执行不同的逻辑。

结束:办法总是有的无非就是花多少时间的问题。如果对您有帮助请点个赞,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值