@alicloud/cloud-charts
Version:

384 lines (378 loc) • 14.6 kB
JavaScript
'use strict';
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
var _excluded = ["line", "area", "filter"],
_excluded2 = ["title", "position", "align", "style", "offsetY", "offsetX"];
import { getStatusColor, pxToNumber } from './common';
import themes from '../themes';
import { warn } from './log';
/**
* 绘制辅助标记通用函数
*
* @param {Chart} chart 图表实例
* @param {object} config 图表配置项
*
* */
export default function (chart, config) {
var guide = config.guide;
if (!guide || guide.visible === false) {
return;
}
var guideLine = guide.line,
guideArea = guide.area,
guideFilter = guide.filter,
other = _objectWithoutPropertiesLoose(guide, _excluded);
if (guideLine) {
if (Array.isArray(guideLine)) {
guideLine.forEach(function (line) {
drawGuideLine(chart, line, config);
});
} else {
drawGuideLine(chart, guideLine, config);
}
}
if (guideArea) {
if (Array.isArray(guideArea)) {
guideArea.forEach(function (area) {
drawGuideArea(chart, area);
});
} else {
drawGuideArea(chart, guideArea);
}
}
if (guideFilter) {
if (Array.isArray(guideFilter)) {
guideFilter.forEach(function (filter) {
drawGuideFilter(chart, filter, config);
});
} else {
drawGuideFilter(chart, guideFilter, config);
}
}
if (!guideLine && !guideArea && !guideFilter && Object.keys(other).length > 0) {
warn('config.guide', '配置异常,请使用 guide.line、guide.area、guide.filter');
}
}
// 计算 scale 排除 range 后的最大最小值
function getMinValue(scale) {
return scale.min - scale.range[0] * (scale.max - scale.min) / (scale.range[1] - scale.range[0]);
}
function getMaxValue(scale) {
return scale.min + (1 - scale.range[0]) * (scale.max - scale.min) / (scale.range[1] - scale.range[0]);
}
export function drawGuideLine(chart, guideLine, config) {
var _guideLine$top = guideLine.top,
top = _guideLine$top === void 0 ? true : _guideLine$top,
text = guideLine.text,
status = guideLine.status,
axis = guideLine.axis,
value = guideLine.value,
start = guideLine.start,
end = guideLine.end,
_guideLine$style = guideLine.style,
style = _guideLine$style === void 0 ? {} : _guideLine$style;
var rawText = text || '';
var _ref = typeof rawText === 'string' ? {
title: rawText
} : rawText,
title = _ref.title,
titlePosition = _ref.position,
titleAlign = _ref.align,
_ref$style = _ref.style,
textStyle = _ref$style === void 0 ? {} : _ref$style,
offsetY = _ref.offsetY,
offsetX = _ref.offsetX,
textConfig = _objectWithoutPropertiesLoose(_ref, _excluded2);
var color = getStatusColor(status);
// 更新处理文本位置
var defaultOffsetY = pxToNumber(themes['widgets-font-size-1']);
var defaultOffsetX = 0;
warn('config.guide', '辅助线暂时不支持柱图镜面和横向的时候开启渐变');
if (offsetY !== undefined) {
defaultOffsetY = offsetY;
// 不是镜面和横向的时候
} else if (!(config !== null && config !== void 0 && config.facet) || (config === null || config === void 0 ? void 0 : config.column) !== false) {
if (axis === 'y') {
defaultOffsetY = -(pxToNumber(themes['widgets-font-size-1']) / 2);
}
}
if (offsetX !== undefined) {
defaultOffsetX = offsetX;
}
var guideConfig = {
top: top,
style: _extends({
stroke: color,
// 默认为虚线
lineDash: [4, 4]
}, style),
text: _extends({
content: title || '',
position: titlePosition || 'start',
style: _extends({
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, yScales) {
var _yScales$axis, _ref2;
var xValue = 'min';
if (!Array.isArray(xScales) && (xScales.isCategory || xScales.x && xScales.x.isCategory)) {
// @ts-ignore 如果x轴是分类型数据,计算 range 外的最小值以铺满绘图区域
xValue = getMinValue(xScales.x || xScales);
}
var yValue = value;
if ((yScales === null || yScales === void 0 ? void 0 : (_yScales$axis = yScales[axis]) === null || _yScales$axis === void 0 ? void 0 : _yScales$axis.min) >= value) {
var _yScales$axis2;
// 当辅助线低于x轴时,直接贴底展示
yValue = yScales === null || yScales === void 0 ? void 0 : (_yScales$axis2 = yScales[axis]) === null || _yScales$axis2 === void 0 ? void 0 : _yScales$axis2.min;
}
return _ref2 = {
x: xValue
}, _ref2[axis] = yValue, _ref2;
};
// 函数接受两个参数 xScales 和 yScales
guideConfig.end = function (xScales, yScales) {
var _yScales$axis3, _ref3;
var 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);
}
}
var yValue = value;
if ((yScales === null || yScales === void 0 ? void 0 : (_yScales$axis3 = yScales[axis]) === null || _yScales$axis3 === void 0 ? void 0 : _yScales$axis3.min) >= value) {
var _yScales$axis4;
// 当辅助线低于x轴时,直接贴底展示
yValue = yScales === null || yScales === void 0 ? void 0 : (_yScales$axis4 = yScales[axis]) === null || _yScales$axis4 === void 0 ? void 0 : _yScales$axis4.min;
}
return _ref3 = {
x: xValue
}, _ref3[axis] = yValue, _ref3;
};
}
}
if (start) {
guideConfig.start = start;
}
if (end) {
guideConfig.end = end;
}
// 横向柱图,修改默认值
if ((config === null || config === void 0 ? void 0 : 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 定义不全');
}
}
export function drawGuideArea(chart, guideArea) {
var _guideArea$top = guideArea.top,
top = _guideArea$top === void 0 ? true : _guideArea$top,
status = guideArea.status,
axis = guideArea.axis,
value = guideArea.value,
start = guideArea.start,
end = guideArea.end,
_guideArea$style = guideArea.style,
style = _guideArea$style === void 0 ? {} : _guideArea$style;
var color = getStatusColor(status);
var guideConfig = {
top: top,
style: _extends({
fill: color
}, style),
// @ts-ignore
start: undefined,
// @ts-ignore
end: undefined
};
if (axis && Array.isArray(value) && value.length > 1) {
if (axis === 'x') {
// y 轴是分类型数据的情况比较少,暂时不处理
guideConfig.start = [value[0], 'min'];
guideConfig.end = [value[1], 'max'];
} else if (axis === 'y' || /y\d/.test(axis)) {
// 形似 y0, y1 ...的axis,说明是多Y轴,多轴的情况下,start/end 必须返回原始数据格式才能正确匹配y轴度量
// 函数接受两个参数 xScales 和 yScales
guideConfig.start = function (xScales, yScales) {
var _yScales$axis5, _ref4;
var xValue = 'min';
if (!Array.isArray(xScales) && (xScales.isCategory || xScales.x && xScales.x.isCategory)) {
// @ts-ignore 如果x轴是分类型数据,计算 range 外的最小值以铺满绘图区域
xValue = getMinValue(xScales.x || xScales);
}
var yValue = value[0];
if ((yScales === null || yScales === void 0 ? void 0 : (_yScales$axis5 = yScales[axis]) === null || _yScales$axis5 === void 0 ? void 0 : _yScales$axis5.min) >= value[0]) {
var _yScales$axis6;
// 当辅助线低于x轴时,直接贴底展示
yValue = yScales === null || yScales === void 0 ? void 0 : (_yScales$axis6 = yScales[axis]) === null || _yScales$axis6 === void 0 ? void 0 : _yScales$axis6.min;
}
return _ref4 = {
x: xValue
}, _ref4[axis] = yValue, _ref4;
};
// 函数接受两个参数 xScales 和 yScales
guideConfig.end = function (xScales, yScales) {
var _yScales$axis7, _ref5;
var 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);
}
}
var yValue = value[1];
if ((yScales === null || yScales === void 0 ? void 0 : (_yScales$axis7 = yScales[axis]) === null || _yScales$axis7 === void 0 ? void 0 : _yScales$axis7.min) >= value[1]) {
var _yScales$axis8;
// 当辅助线低于x轴时,直接贴底展示
yValue = yScales === null || yScales === void 0 ? void 0 : (_yScales$axis8 = yScales[axis]) === null || _yScales$axis8 === void 0 ? void 0 : _yScales$axis8.min;
}
return _ref5 = {
x: xValue
}, _ref5[axis] = yValue, _ref5;
};
}
}
if (start) {
guideConfig.start = start;
}
if (end) {
guideConfig.end = end;
}
if (guideConfig.start && guideConfig.end) {
chart.annotation().region(guideConfig);
} else {
warn('config.guide', 'area 定义不全');
}
}
export function drawGuideFilter(chart, guideFilter, config) {
var _guideFilter$top = guideFilter.top,
top = _guideFilter$top === void 0 ? true : _guideFilter$top,
status = guideFilter.status,
axis = guideFilter.axis,
value = guideFilter.value,
start = guideFilter.start,
end = guideFilter.end,
apply = guideFilter.apply,
style = guideFilter.style,
_guideFilter$useGradi = guideFilter.useGradient,
useGradient = _guideFilter$useGradi === void 0 ? false : _guideFilter$useGradi;
var color = getStatusColor(status);
var guideColor = color;
// 如果镜面或横向不处理
if (!!(config !== null && config !== void 0 && config.facet) || (config === null || config === void 0 ? void 0 : config.column) === false) {
guideColor = color;
} else if (axis === 'y' && useGradient) {
// TODO 考虑方向
guideColor = "l(90) 0:" + color + " 1:" + color + "00";
}
var guideConfig = {
top: top,
color: guideColor,
apply: apply,
style: style,
// @ts-ignore
start: undefined,
// @ts-ignore
end: undefined
};
if (axis && Array.isArray(value) && value.length > 1) {
if (axis === 'x') {
// y 轴是分类型数据的情况比较少,暂时不处理
guideConfig.start = [value[0], 'min'];
guideConfig.end = [value[1], 'max'];
} else if (axis === 'y' || /y\d/.test(axis)) {
// 形似 y0, y1 ...的axis,说明是多Y轴,多轴的情况下,start/end 必须返回原始数据格式才能正确匹配y轴度量
// 函数接受两个参数 xScales 和 yScales
guideConfig.start = function (xScales) {
var _ref7;
if (!Array.isArray(xScales) && (xScales.isCategory || xScales.x && xScales.x.isCategory)) {
var _ref6;
// 如果x轴是分类型数据,使用[-0.5, length - 0.5]的索引值来让辅助线铺满绘图区域
return _ref6 = {
x: -0.5
}, _ref6[axis] = value[0], _ref6;
}
return _ref7 = {
x: 'min'
}, _ref7[axis] = value[0], _ref7;
};
// 函数接受两个参数 xScales 和 yScales
guideConfig.end = function (xScales) {
var _ref10;
if (!Array.isArray(xScales)) {
// 如果x轴是分类型数据,使用[-0.5, length - 0.5]的索引值来让辅助线铺满绘图区域
if (xScales.x && xScales.x.isCategory) {
var _ref8;
return _ref8 = {
x: xScales.x.values.length - 0.5
}, _ref8[axis] = value[1], _ref8;
}
if (xScales.isCategory) {
var _ref9;
// @ts-ignore G2 的类型声明和实际传入不同,暂时忽略报错
return _ref9 = {
x: xScales.values.length - 0.5
}, _ref9[axis] = value[1], _ref9;
}
}
return _ref10 = {
x: 'max'
}, _ref10[axis] = value[1], _ref10;
};
}
}
if (start) {
guideConfig.start = start;
}
if (end) {
guideConfig.end = end;
}
if (guideConfig.start && guideConfig.end) {
chart.annotation().regionFilter(guideConfig);
} else {
warn('config.guide', 'filter 定义不全');
}
}