简介:实现思路纯为本人所想,欢迎交流,考虑拓展场景才自己去实现一个图表,但是单纯也是为了好玩才去实现的,代码冗余部分欢迎给出优化建议,但是均不采纳,因为懒得去优化。
实现思路:图文结合
/**
* 将 dataItems 处理成需要的数据结构类型
*
* @param {Object} series - 数据系列,包含需要处理的数据
* @param {string} position - 数据位置,决定数据的排列顺序
* @param {string} increase_color - 上升数据的颜色
* @param {string} decrease_color - 下降数据的颜色
* @param {string} sum_color - 累计数据的颜色
* @returns {Array} - 返回经过处理后的数据结构
*/
function processDataItems(
series,
position,
increase_color,
decrease_color,
sum_color
) {
// 获取唯一的 ID 生成器
const idUniqueHandler = uniqueHandler();
// 复制第一个系列配置
const seriesItemConfig = { ...series[0] };
// 创建虚拟对象,用于瀑布图的初始结构
const virtualObject = {
...seriesItemConfig,
data: [],
label: { show: false },
emphasis: { label: { show: false } },
id: idUniqueHandler('virtualObject#waterFallFigure'),
relatedSeriesName: seriesItemConfig.name,
barMinHeight: 0,
stack: 'Total',
isVisualSeries: true,
tooltip: { show: false },
};
// 顶部对象,用于显示正数
const topObject = {
...seriesItemConfig,
data: [],
stack: 'Total',
};
// 底部对象,用于显示负数
const bottomObject = {
...seriesItemConfig,
data: [],
id: idUniqueHandler('bottomObject#waterFallFigure'),
stack: 'Total',
barMinHeight: 0,
relatedSeriesName: seriesItemConfig.name,
isVisualSeries: true,
};
const seriesData = series[0].data;
const len = seriesData.length;
const resData = [];
let currentVirtualValue = 0;
let lastVirtualValue = 0;
let sum = 0;
// 遍历数据系列,构建瀑布图数据结构
for (let i = 0; i < len; i++) {
const item = seriesData[i];
sum += item.value;
const isPositiveValue = Math.sign(item.value) >= 0;
const isPositiveVirtualValue = Math.sign(currentVirtualValue) >= 0;
// 处理正数的逻辑
if (isPositiveValue) {
if (i === 0 || isPositiveVirtualValue) {
topObject.data.push({
...item,
value: item.value,
itemStyle: { color: increase_color },
});
bottomObject.data.push({ ...item, value: 0, label: { show: false } });
virtualObject.data.push({
...item,
value: currentVirtualValue,
itemStyle: { color: 'transparent' },
tooltip: { show: false }
});
currentVirtualValue += item.value;
} else {
lastVirtualValue = currentVirtualValue;
currentVirtualValue += item.value;
if (Math.sign(lastVirtualValue) < 0 && Math.sign(currentVirtualValue) < 0) {
topObject.data.push({
...item,
value: -item.value,
itemStyle: { color: increase_color },
});
bottomObject.data.push({ ...item, value: 0, label: { show: false } });
virtualObject.data.push({
...item,
value: currentVirtualValue,
itemStyle: { color: 'transparent' },
tooltip: { show: false }
});
} else {
topObject.data.push({
...item,
value: -item.value + currentVirtualValue,
itemStyle: { color: increase_color },
});
bottomObject.data.push({ ...item, value: 0, label: { show: false } });
virtualObject.data.push({
...item,
value: currentVirtualValue,
itemStyle: { color: increase_color },
});
virtualObject.tooltip.show = true;
}
}
} else {
// 处理负数的逻辑
if (i === 0 || !isPositiveVirtualValue) {
topObject.data.push({ ...item, value: 0, label: { show: false } });
bottomObject.data.push({
...item,
value: item.value,
itemStyle: { color: decrease_color },
});
virtualObject.data.push({
...item,
value: currentVirtualValue,
itemStyle: { color: 'transparent' },
tooltip: { show: false }
});
currentVirtualValue += item.value;
} else {
lastVirtualValue = currentVirtualValue;
currentVirtualValue += item.value;
if (Math.sign(lastVirtualValue) > 0 && Math.sign(currentVirtualValue) > 0) {
topObject.data.push({ ...item, value: 0, label: { show: false } });
bottomObject.data.push({
...item,
value: -item.value,
itemStyle: { color: decrease_color },
});
virtualObject.data.push({
...item,
value: currentVirtualValue,
itemStyle: { color: 'transparent' },
tooltip: { show: false }
});
} else {
topObject.data.push({ ...item, value: 0, label: { show: false } });
bottomObject.data.push({
...item,
value: -item.value + currentVirtualValue,
itemStyle: { color: decrease_color },
});
virtualObject.data.push({
...item,
value: currentVirtualValue,
itemStyle: { color: decrease_color },
});
virtualObject.tooltip.show = true;
}
}
}
}
// 添加累计数据项
virtualObject.data.push({ value: 0, name: '累计', label: { show: false } });
topObject.data.push({ value: sum, name: '累计', itemStyle: { color: sum_color } });
bottomObject.data.push({ value: 0, name: '累计', label: { show: false } });
// 如果位置在左侧,反转数据顺序
if (position === 'left') {
virtualObject.data.reverse();
topObject.data.reverse();
bottomObject.data.reverse();
}
// 返回处理好的数据结构
resData.push({ ...virtualObject, barMinHeight: 0 }, { ...topObject, barMinHeight: 0 }, { ...bottomObject, barMinHeight: 0 });
return resData;
}
/**
* 处理 formater 数据
*
* @param {Array} resData - 包含瀑布图数据结构的数组
* @returns {Array} - 返回处理后的数据结构
*/
function processFormaterData(resData) {
// 获取各个数据对象的引用
const virtualObjData = resData[0].data;
const topObjData = resData[1].data;
const bottomObjData = resData[2].data;
// 获取虚拟对象数据的长度
const virtualObjDataLen = virtualObjData.length;
// 遍历每个虚拟对象数据项,进行格式化处理
for (let i = 0; i < virtualObjDataLen; i++) {
// 检查当前虚拟数据项的值是否有效且不透明
if (virtualObjData[i].value !== 0 && virtualObjData[i].itemStyle.color !== "transparent") {
// 处理顶部对象数据
if (topObjData[i].value !== 0 && !isNaN(topObjData[i].value) && !isNaN(virtualObjData[i].value)) {
_.merge(virtualObjData[i], {
formatValue: Number(virtualObjData[i].value) + Number(topObjData[i].value)
});
_.merge(topObjData[i], {
formatValue: Number(virtualObjData[i].value) + Number(topObjData[i].value)
});
} else {
// 处理底部对象数据
if (bottomObjData[i].value !== 0 && !isNaN(virtualObjData[i].value) && !isNaN(bottomObjData[i].value)) {
_.merge(virtualObjData[i], {
formatValue: Number(virtualObjData[i].value) + Number(bottomObjData[i].value)
});
_.merge(bottomObjData[i], {
formatValue: Number(virtualObjData[i].value) + Number(bottomObjData[i].value)
});
}
}
}
}
// 合并处理后的数据返回
_.merge(resData[0], { data: virtualObjData });
_.merge(resData[1], { data: topObjData });
_.merge(resData[2], { data: bottomObjData });
return resData;
}
本文函数中返回的内容为series值,如有疑问欢迎打扰