in src/rule/extremeData.ts [6:251]
export function processBarExtremeData(chartObj: any, config: any, data: any) {
const { dataSize, size } = chartObj;
const width = size[0];
const { force } = chartObj.props;
const chartName = chartObj?.chartRule?.name;
// 图表宽度,50是估算的padding
const length = width - 50;
// 根据stack、dodgeStack等配置项计算一组柱子的宽度,从而计算至少需要几组柱子
const barWidth = 24;
const types = Array.from(new Set(data?.map((item: any) => item?.type)))?.length ?? 0;
const dodges = Array.from(new Set(data?.map((item: any) => item?.dodge)))?.length ?? 1;
const groups = config?.dodgeStack ? dodges : config?.stack ? 1 : types;
const minCount = Math.floor(length / (groups * barWidth + 80));
if (dataSize < minCount) {
if (force === true || force?.extreme === true) {
warn(chartName, '当前柱图数据量较少,推荐关闭force配置项开启极端数据自适应。问题码#08');
return {
isExtreme: true,
};
}
// x轴类型
const axisType = config?.xAxis?.type ?? 'cat';
// 原数据中类型
const dataTypes = Array.from(new Set(data.map((x: any) => x.type)));
// 颜色
let colors = config?.colors ?? themes.category_20;
if (Array.isArray(colors) && colors.length < dataTypes.length) {
if (
!(colors.length === 12 && themes.category_12?.every((val, index) => val === colors?.[index])) &&
!(colors.length === 20 && themes.category_20?.every((val, index) => val === colors?.[index]))
) {
colors = [...colors, ...(themes.category_20?.slice(colors.length, dataTypes.length) || [])];
}
while (colors.length < dataTypes.length) {
colors = [...colors, ...colors.slice(0, dataTypes.length - colors.length)];
}
}
const newData = [...data];
let newColors = colors;
let xAxis = {};
const { extreme } = force ?? {};
let needColor = false;
let alignLeft = false;
let showPlaceholder = false;
// 计算最后一个柱子的y值
const xValues = Array.from(new Set(data.map((item: any) => item.x)));
const lastX = xValues[xValues.length - 1];
const dodges = Array.from(new Set(data.map((item: any) => item.dodge)));
const lastDodge = dodges[dodges.length - 1];
let lastY = 0;
if (config.dodgeStack && lastDodge) {
lastY = data
.filter((item: any) => item.x === lastX && item.dodge === lastDodge)
.map((item: any) => item.y || 0)
.reduce((pre: number, cur: number) => pre + cur, 0);
} else if (config.stack) {
lastY = data
.filter((item: any) => item.x === lastX)
.map((item: any) => item.y || 0)
.reduce((pre: number, cur: number) => pre + cur, 0);
} else if (config.dodge && lastDodge) {
const filteredData = data.filter((item: any) => item.x === lastX && item.dodge === lastDodge);
lastY = filteredData[filteredData.length - 1].y;
} else {
const filteredData = data.filter((item: any) => item.x === lastX);
lastY = filteredData[filteredData.length - 1].y;
}
// 分类数据
if (axisType === 'cat') {
// 分类数据默认隐藏占位
// 是否左对齐
// 优先级: 用户配置>特殊情况(数据量为1)>默认配置
/*
alignLeft =
force === false || extreme === false || extreme?.alignLeft === false
? true
: extreme === true || extreme?.alignLeft === true
? false
: dataSize === 1;
*/
alignLeft = force === false || extreme === false || extreme?.alignLeft === false;
// 是否显示占位
// 优先级:用户配置>默认配置
showPlaceholder = force === false || extreme === false || extreme?.showPlaceholder === false;
// 左对齐,无占位
if (alignLeft && !showPlaceholder) {
const values = Array.from(new Set(data.map((item: any) => item.x)));
for (let i = 0; i < minCount - dataSize; i += 1) {
values.push(`widgets-pad-${i}`);
}
xAxis = { values };
warn(chartName, '当前数据量较少,已默认开启左对齐,推荐通过extreme配置项开启占位补全。问题码#08');
}
// 左对齐且显示占位
else if (alignLeft && showPlaceholder) {
for (let i = 0; i < minCount - dataSize; i += 1) {
newData.push({
x: `widgets-pad-${i}`,
y: lastY,
type: 'widgets-pad-type',
});
}
needColor = true;
warn(chartName, '当前数据量较少,已默认开启左对齐与占位补全,可通过extreme配置项进行关闭。问题码#08');
}
// 无特殊处理
else {
warn(chartName, '当前数据量较少,推荐通过extreme配置项开启左对齐与占位补全。问题码#08');
}
}
// 时间分类数据
else if (axisType === 'timeCat') {
// 计算最后一个柱子的y值
/*
let lastY = data?.[0]?.y ?? 0;
let curMax = data?.[0]?.x ?? 0;
data.forEach((item: any) => {
if (item.x > curMax) {
curMax = item.x;
lastY = item.y;
}
});
*/
// 时间分类数据默认开启
// 是否左对齐
// 优先级: 用户配置>默认配置
//alignLeft = !(extreme === true || extreme?.alignLeft === true);
alignLeft = force === false || extreme === false || extreme?.alignLeft === false;
// 是否显示占位
// 优先级:用户配置>默认配置
showPlaceholder = !(extreme === true || extreme?.showPlaceholder === true);
const values = Array.from(new Set(data.map((item: any) => item.x)));
const minX = Math.min(...(values as number[]));
const maxX = Math.max(...(values as number[]));
const step = maxX !== minX ? Math.floor((maxX - minX) / dataSize) : 100;
// 左对齐,无占位
if (alignLeft && !showPlaceholder) {
const newValues = [...values];
for (let i = 0; i < minCount - dataSize; i += 1) {
newValues.push(maxX + step * (i + 1));
}
xAxis = { values: newValues, ticks: values };
warn(chartName, '当前数据量较少,已默认开启左对齐,推荐通过extreme配置项开启占位补全。问题码#08');
}
// 左对齐且显示占位
else if (alignLeft && showPlaceholder) {
for (let i = 0; i < minCount - dataSize; i += 1) {
newData.push({
x: maxX + step * (i + 1),
y: lastY,
type: 'widgets-pad-type',
});
}
xAxis = {
ticks: values,
};
needColor = true;
warn(chartName, '当前数据量较少,已默认开启左对齐与占位补全,可通过extreme配置项进行关闭。问题码#08');
}
// 无特殊处理
else {
warn(chartName, '当前数据量较少,推荐通过extreme配置项开启左对齐与占位补全。问题码#08');
}
}
if (needColor) {
// 颜色处理
if (Array.isArray(colors)) {
newColors = [...colors.slice(0, dataTypes.length), themes['widgets-color-container-background']];
} else if (typeof colors === 'string') {
newColors = [...dataTypes.map(() => colors), themes['widgets-color-container-background']];
} else if (typeof colors === 'function') {
newColors = (type: string) => {
if (type === 'widgets-pad-type') {
return themes['widgets-color-container-background'];
} else {
return colors(type);
}
};
}
}
return {
isExtreme: true,
data: newData,
config: {
...(alignLeft
? {
legend:
config?.legend === false || config?.legend?.visible === false
? false
: {
items: dataTypes.map((t: any, index: number) => ({
name: t,
value: t,
marker: {
symbol: 'square',
style: {
fill: Array.isArray(newColors) ? newColors[index] : newColors(t),
},
},
})),
...(config?.legend || {}),
},
xAxis:
config?.xAxis === false || config?.xAxis?.visible === false
? false
: {
...xAxis,
autoHide: false,
autoEllipsis: true,
...(config?.xAxis || {}),
},
}
: {}),
...(alignLeft && showPlaceholder
? {
colors: newColors,
tooltip: false,
}
: {}),
},
};
}
return {
isExtreme: false,
};
}