in src/common/guide.ts [90:242]
export function drawGuideLine(chart: Chart | View, guideLine: GuideLineConfig, config?: any) {
const { top = true, text, status, axis, value, start, end, style = {} } = guideLine;
const rawText = text || '';
const {
title,
position: titlePosition,
align: titleAlign,
style: textStyle = {},
offsetY,
offsetX,
...textConfig
} = (typeof rawText === 'string' ? { title: rawText } : rawText) as GuideLineTextConfig;
const color = getStatusColor(status);
// 更新处理文本位置
let defaultOffsetY = pxToNumber(themes['widgets-font-size-1']);
let defaultOffsetX = 0;
warn('config.guide', '辅助线暂时不支持柱图镜面和横向的时候开启渐变');
if (offsetY !== undefined) {
defaultOffsetY = offsetY;
// 不是镜面和横向的时候
} else if (!config?.facet || config?.column !== false) {
if (axis === 'y') {
defaultOffsetY = -(pxToNumber(themes['widgets-font-size-1']) / 2);
}
}
if (offsetX !== undefined) {
defaultOffsetX = offsetX;
}
const guideConfig = {
top,
style: {
stroke: color,
// 默认为虚线
lineDash: [4, 4],
...style,
},
text: {
content: title || '',
position: titlePosition || 'start',
style: {
fill: color,
textAlign: titleAlign || ((titlePosition || 'start') === 'start' ? 'start' : 'end'),
...textStyle,
},
// X 轴时关闭自动旋转
autoRotate: axis !== 'x',
offsetY: defaultOffsetY,
offsetX: defaultOffsetX,
...textConfig,
},
// @ts-ignore
start: undefined,
// @ts-ignore
end: undefined,
};
// 判断value时需要注意数字0是假值,但是是一个合理的guide value
if (axis && (value || value === 0)) {
if (axis === 'x') {
// y 轴是分类型数据的情况比较少,暂时不处理
guideConfig.start = [value, 'min'];
guideConfig.end = [value, 'max'];
// x 轴辅助线,修改position和textAlign默认值
guideConfig.text.position = titlePosition || 'end';
guideConfig.text.style.textAlign = titleAlign || 'center';
guideConfig.text.offsetY = offsetY || 0;
} else if (axis === 'y' || /y\d/.test(axis)) {
// 形似 y0, y1 ...的axis,说明是多Y轴,多轴的情况下,start/end 必须返回原始数据格式才能正确匹配y轴度量
// 函数接受两个参数 xScales 和 yScales
guideConfig.start = function (
xScales: G2Dependents.Scale[] | Record<string, G2Dependents.Scale>,
yScales: Record<string, G2Dependents.Scale>,
) {
let xValue = 'min';
if (
!Array.isArray(xScales) &&
(xScales.isCategory || (xScales.x && xScales.x.isCategory))
) {
// @ts-ignore 如果x轴是分类型数据,计算 range 外的最小值以铺满绘图区域
xValue = getMinValue(xScales.x || xScales);
}
let yValue = value;
if (yScales?.[axis]?.min >= value) {
// 当辅助线低于x轴时,直接贴底展示
yValue = yScales?.[axis]?.min;
}
return {
x: xValue,
[axis]: yValue,
};
};
// 函数接受两个参数 xScales 和 yScales
guideConfig.end = function (
xScales: G2Dependents.Scale[] | Record<string, G2Dependents.Scale>,
yScales: Record<string, G2Dependents.Scale>,
) {
let xValue = 'max';
if (!Array.isArray(xScales)) {
// 如果x轴是分类型数据,计算 range 外的最大值以铺满绘图区域
if (xScales.x && xScales.x.isCategory) {
xValue = getMaxValue(xScales.x);
}
if (xScales.isCategory) {
// @ts-ignore G2 的类型声明和实际传入不同,暂时忽略报错
xValue = getMaxValue(xScales);
}
}
let yValue = value;
if (yScales?.[axis]?.min >= value) {
// 当辅助线低于x轴时,直接贴底展示
yValue = yScales?.[axis]?.min;
}
return {
x: xValue,
[axis]: yValue,
};
};
}
}
if (start) {
guideConfig.start = start;
}
if (end) {
guideConfig.end = end;
}
// 横向柱图,修改默认值
if (config?.column == false) {
if (axis === 'x') {
guideConfig.text.offsetY = offsetY || -(pxToNumber(themes['widgets-font-size-1']) / 2);
guideConfig.text.style.textAlign = titleAlign || 'end';
} else {
guideConfig.text.autoRotate = false;
guideConfig.text.position = titlePosition || 'end';
guideConfig.text.offsetY = offsetY || -(pxToNumber(themes['widgets-font-size-1']) / 2);
guideConfig.text.style.textAlign = titleAlign || 'center';
}
}
if (guideConfig.start && guideConfig.end) {
chart.annotation().line(guideConfig);
} else {
warn('config.guide', 'line 定义不全');
}
}