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 类型来确定执行不同的逻辑。
结束:办法总是有的无非就是花多少时间的问题。如果对您有帮助请点个赞,谢谢。