思路
话不多说,ui图如下
拿到这个ui图的时候就知道不简单了,柱状图简单,斜切功能又怎么实现了,于是查找资料
发现这个功能很像(来源:横向柱图斜切 - ECharts图表集,echarts gallery社区,Make A Pie,分享你的可视化作品isqqw.com)
尝试发现当值为负数的时候样式爆炸,效果如图
这个方案只能放弃,于是决定用自定义 custom实现了 思路很简单,就是画出柱状图和label,负数的柱状图我放在右边是因为数据太大会和y轴的值重合了,着急下班,就贴出最终代码了
最终代码
return {
tooltip: {
show: true,
backgroundColor: '#012C68',
borderColor: '#012C68',
extraCssText: 'box-shadow: 0 0 10px 0 rgba(0, 119, 255, 0.50) inset', // 添加阴影以突出显示
axisPointer: {
type: 'shadow',
},
textStyle: {
color: '#fff', // 设置文字颜色为深色,以便在白色背景下清晰可见
},
className: 'my-custom-tooltip',
formatter: function (params) {
// params 是提示框触发时的数据信息
if (params.data) {
const type = params.data.type; // 节点名称
const unit = params.data.unit || '';
const name = params.name; // 节点名称
const value = params.data.value || ''; // 值(你传的是 column4)
return `
<div style="border-bottom: 1px solid #ccc; padding-bottom: 5px; margin-bottom: 5px;">
<strong style="
max-width: 150px;
display: inline-block;
white-space: normal; /* 允许换行(关键!) */
word-wrap: break-word; /* 长单词/连续字符可断行 */
overflow-wrap: break-word; /* 现代标准写法 */
">${name}</strong>
</div>
${type}:${value}${unit}
`.replace(/\n/g, '');
}
return '';
},
},
xAxis: {
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
formatter: function (value) {
return value;
},
},
splitLine: {
show: true,
lineStyle: {
color: '#fff',
type: 'dashed', // 虚线
opacity: 0.2,
},
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'category',
data: data.map((v) => `${v.index} ${v.orgName}`),
axisLabel: {
color: '#fff',
fontSize: 14,
width: 120,
// 当内容超出宽度时使用省略号
overflow: 'truncate',
ellipsis: '...',
align: 'left',
margin: 120,
formatter: (value) => `{arrow|} ${value}`,
rich: {
arrow: {
backgroundColor: {
image: arrow,
},
backgroundRepeat: 'no-repeat',
// 关键:通过 padding 控制垂直位置
},
},
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
grid: {
top: 20, // 上边距
left: -110, // 左边距
right: 30, // 右边距
bottom: 20, // 下边距
containLabel: true, // 如果为true,则确保网格包含坐标轴标签
},
series: [
{
data: data.map((v) => {
return { ...v };
}),
type: 'custom',
renderItem: function (params, api) {
const value = api.value(0);
const categoryIndex = api.value(1);
// 获取坐标(绝对像素)
const zeroPoint = api.coord([0, categoryIndex]);
const valuePoint = api.coord([value, categoryIndex]);
const barHeight = api.size([0, 1])[1] * 0.3; // 更细
const y = zeroPoint[1] - barHeight / 2;
const cut = 8;
const x0 = zeroPoint[0];
const x1 = valuePoint[0];
const width = Math.abs(x1 - x0); // 使用绝对值计算宽度
let points, labelX, labelY, gradient, bar, labelText, group;
if (value > 0 && width > cut) {
// 正值且足够宽做斜切
points = [
[x0, y],
[x1, y],
[x1 - cut, y + barHeight],
[x0, y + barHeight],
];
gradient = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#016AFF' },
{ offset: 1, color: '#4AE5FF' },
]);
labelX = x1 - cut + 20;
labelY = y + barHeight / 2;
} else if (value < 0 && width > cut) {
points = [
[x0, y],
[x1 + cut, y],
[x1, y + barHeight],
[x0, y + barHeight],
];
gradient = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#016AFF' },
{ offset: 1, color: '#4AE5FF' },
]);
// 因为y轴设置为
// labelX = x1 - cut - 10;
labelX = x0 + 20;
labelY = y + barHeight / 2;
} else {
points = [
[Math.min(x0, x1), y],
[Math.max(x0, x1), y],
[Math.max(x0, x1), y + barHeight],
[Math.min(x0, x1), y + barHeight],
];
gradient = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#016AFF' },
{ offset: 1, color: '#4AE5FF' },
]);
labelX = value >= 0 ? x1 + 20 : x1 - 20;
labelY = y + barHeight / 2;
}
bar = {
type: 'polygon',
shape: { points: points },
style: { fill: gradient },
key: params.dataIndex,
info: { value: value },
};
labelText = {
type: 'text',
style: {
text: value.toString(),
textAlign: 'center',
textVerticalAlign: 'middle',
fill: '#FFFFFF', // 白色文本
fontSize: 14,
},
position: [labelX, labelY],
};
group = {
type: 'group',
children: [bar, labelText],
};
return group; // 返回组对象
},
},
],
};