在echarts中,我们很多时候都会用到散点图,但是基础的散点图不一定能满足我们的需求,往往都会遇到提示框进行自定义,散点重合提示框显示如何解决,类型对应等一系列问题,那么我们该如何解决呢?
废话不多说,直接上代码:
//散点图
setPaperChart = function (detail) {
// 获取 chart 元素
const chartDom = this.$refs.paperChart;
// 初始化 echarts
const myChart = echarts.init(chartDom);
// 构建 scatter plot 的数据
const scatterData = detail.map((item) => {
return {
//散点形状设置symbol: 'circle’,
// ‘rect’,
// ‘roundRect’,
// ‘triangle’,
// ‘diamond’,
// ‘pin’,
// 'arrow’
value: [item.likelihood, item.impactSum],
symbol: item.auditType === '1' ? 'circle' : 'diamond',
tooltip: {
formatter: (params) => {
if (!window.dataItem) {
window.dataItem = {}
}
// 获取重复散点的索引列表
const duplicateIndexes = detail.reduce((acc, curr, i) => {
if (curr.likelihood === item.likelihood && curr.impactSum === item.impactSum) {
acc.push(i);
}
return acc;
}, []);
let tooltipContent = '';
if (duplicateIndexes.length > 1) {
tooltipContent = `<div style="height: 200px;overflow: auto;-ms-overflow-style: none; scrollbar-width: none"> `;
}
duplicateIndexes.forEach((duplicateIndex) => {
const borderStyle1 = "display:inline-block; margin-right: 4px; border-bottom: 1px solid rgb(42,130,228); width: 20px; margin-top: 5px; margin-bottom: 5px;"
const borderStyle2 = "display:inline-block; margin-right: 4px; border-bottom: 1px solid rgb(212,48,48); width: 20px; margin-top: 5px; margin-bottom: 5px;"
const duplicateItem = detail[duplicateIndex]
let markerStyle = `<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:${params.color};"></span>`;
if (duplicateItem.auditType === '2') {
markerStyle = `<span style="background-color:${params.color}; width:5px; height: 5px; border: 2px solid ${params.color}; transform: rotate(45deg); display: inline-block; margin-left: 2px;margin-right: 5px;"></span>`;
}
window.dataItem[duplicateIndex] = JSON.stringify(duplicateItem)
tooltipContent += `
<div style="display: flex;justify-content: center;align-items: stretch;gap:40px;padding: 20px">
<div>
<div>
<span style="${borderStyle1}"></span>
财务金额:${this.getDictText(duplicateItem.amountLevel.toString(), this.AmountLevelDict)}${'(' + duplicateItem.amountLevel + ')'}
</div>
<div style="margin-top: 5px">
<span style="${borderStyle1}"></span>
合法合规:${this.getDictText(duplicateItem.severityLevel.toString(), this.SeverityLevelDict)}${'(' + duplicateItem.severityLevel + ')'}
</div>
<div style="margin-top: 5px">
<span style="${borderStyle1}"></span>
涉及人群:${this.getDictText(duplicateItem.scopeLevel.toString(), this.ScopeLevelDict)}${'(' + duplicateItem.scopeLevel + ')'}
</div>
<div style="margin-top: 5px">
<span style="${borderStyle1}"></span>
纠正可行性:${this.getDictText(duplicateItem.feasibilityLevel.toString(), this.FeasibilityLevelDict)}${'(' + duplicateItem.feasibilityLevel + ')'}
</div>
<div style="margin-top: 5px">
<span style="${borderStyle2}"></span>
发生概率:${this.getDictText(duplicateItem.likelihood.toString(), this.LikelihoodDict)}${'(' + duplicateItem.likelihood + ')'}
</div>
</div>
<div style="display:flex;flex-direction: column;justify-content: space-between">
<div class="tooltip" title="${duplicateItem.remark}">
${markerStyle}${this.orgMap[duplicateItem.orgId]}->${duplicateItem.remark}
</div>
<div style="border: 2px solid ${params.color}; padding: 5px; background-color:${params.color} ; color: #0a0101;">
风险评估:${this.getDictText(duplicateItem.priorityRanking.toString(), this.PriorityRankingDict)}${'(' + duplicateItem.priorityRanking + ')'}
</div>
<button class="myButtonPrimary" onclick="window.openDraftEvent('${duplicateIndex}')">查看问题</button>
</div>
</div> <hr> `;
})
if (duplicateIndexes.length > 1) {
tooltipContent += `</div>`
}
return tooltipContent;
}
}
}
});
const option = {
tooltip: {
trigger: 'item',
enterable: true,
height: 100,
// 触发方式 mousemove, click, none, mousemove|click
triggerOn: `mousemove`,
formatter: function (params) {
return params.data.tooltip.formatter(params);
}
},
graphic: [
{
type: 'text',
left: 'center',
top: '2%',
style: {
text: '圆点代表xx,菱形代表xxx,值大小对应的颜色变化',
fill: '#333', // 文字颜色
fontSize: 14,
fontWeight: 'bold'
}
}
],
visualMap: {
type: 'continuous', // 连续型
min: 0.1, // 最小值
max: 20, // 最大值
calculable: false, // 是否显示拖拽用的手柄
inRange: {
color: ['#00ff0d', '#00f7ff', '#ff5900', '#ff0051', '#a600ff'], // 颜色范围,可以自定义颜色
},
textStyle: {
color: '#333' // 文字颜色
},
orient: 'horizontal', // 调整图例的方向为水平
right: '12%',
top: '0%'
},
grid: {
left: "6%",
top: "10%",
right: "4%",
},
xAxis: {
splitLine: {show: false}, // 隐藏x轴分割线
axisTick: {show: false}, // 隐藏x轴刻度线
axisLine: {
onZero: false,
lineStyle: {
color: '#100202'
},
symbol: ['none', 'arrow'], // 使用箭头图标
symbolSize: [8, 12], // 箭头大小
symbolOffset: [10, 0], // 箭头位置偏移
symbolRotate: 0 // 箭头旋转角度
},
},
yAxis: {
splitLine: {show: false}, // 隐藏y轴分割线
axisTick: {show: false}, // 隐藏y轴刻度线
axisLine: {
onZero: false,
lineStyle: {
color: '#100202'
},
symbol: ['none', 'arrow'], // 使用箭头图标
symbolSize: [8, 12], // 箭头大小
symbolOffset: [10, 0], // 箭头位置偏移
symbolRotate: 0 // 箭头旋转角度
},
},
series: [
{
symbolSize: 14,
data: scatterData,
type: 'scatter',
}
],
};
// 设置图表配置项
myChart.setOption(option);
}
效果如下图:
1.颜色与值大小渐变:主要是通过visualMap来调色盘来实现的,你可以在inRange中自定义自己需要的颜色;
2.散点的类型,我这里业务需求是需要两种不同类型的,所以我只设置了两种形状,当前你可以设置多种形状,主要是通过symbol来设置的,echarts提供了各种形状的,可以自行选择;
3.提示框自定义:主要操作tooltip,这个提示框我们是可以自己定义的,里面可以写各种类型的标签,但是只能用原生的,使用elementui里面那些组件是不可以的,我这里判断是否是重复散点,就是根据x,y轴的值相同来判断的,如果值相同,我获取到他的索引,push到我的索引集合里面;后面就是一个循环操作了;特别注意的是因为类型不同,如果要区分分别是哪种类型的,用params里面的marker是不可行的,因为parmas 里面的marker默认就是一个圆形的;所以我这里自己定义了markerStyle,颜色和形状都是根据散点来的。
这样就能实现我们如上的效果啦!tooltip里面的某些方法,大家用不到的,可以根据自己的实际情况删除重写哦!数据detail我就不提供了,这个就是一个对象集合,可以让后端的哥们返给你。希望能帮到各位小伙伴!