@alicloud/cloud-charts
Version:

596 lines (492 loc) • 24.2 kB
JavaScript
'use strict';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports["default"] = exports.Bar = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _Base2 = _interopRequireDefault(require("../common/Base"));
var _view = require("@antv/data-set/lib/view");
require("@antv/data-set/lib/transform/percent");
require("@antv/data-set/lib/transform/aggregate");
var _errorWrap = _interopRequireDefault(require("../common/errorWrap"));
var _index = _interopRequireDefault(require("../themes/index"));
var _common = require("../common/common");
var _autoTimeMask = _interopRequireDefault(require("../common/autoTimeMask"));
var _legendFilter = _interopRequireDefault(require("../common/legendFilter"));
var _rectXAxis = _interopRequireDefault(require("../common/rectXAxis"));
var _rectYAxis = _interopRequireDefault(require("../common/rectYAxis"));
var _rectTooltip = _interopRequireDefault(require("../common/rectTooltip"));
var _rectLegend = _interopRequireDefault(require("../common/rectLegend"));
var _guide = _interopRequireDefault(require("../common/guide"));
var _label = _interopRequireDefault(require("../common/label"));
var _geomSize = _interopRequireDefault(require("../common/geomSize"));
var _geomStyle = _interopRequireDefault(require("../common/geomStyle"));
var _rectZoom = _interopRequireDefault(require("../common/rectZoom"));
var _rectScrollbar = _interopRequireDefault(require("../common/rectScrollbar"));
var _rectSlider = _interopRequireDefault(require("../common/rectSlider"));
var _interaction = require("../common/interaction");
var _ChartProvider = require("../ChartProvider");
require("./index.css");
var Bar = /*#__PURE__*/function (_Base) {
(0, _inheritsLoose2["default"])(Bar, _Base);
function Bar() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _Base.call.apply(_Base, [this].concat(args)) || this;
_this.chartName = 'G2Bar';
_this.barDataView = void 0;
return _this;
}
var _proto = Bar.prototype;
_proto.getDefaultConfig = function getDefaultConfig() {
return {
colors: _index["default"].category_12,
// padding: ['auto', 'auto', 'auto', 'auto'],
xAxis: {
type: 'cat',
labelFormatter: null,
// 可以强制覆盖,手动设置label
categories: null,
autoRotate: false,
autoHide: false,
// 分类轴默认不开启抽样显示
autoEllipsis: true
},
yAxis: {
labelFormatter: null,
// 可以强制覆盖,手动设置label
max: null,
min: null
},
legend: {
align: 'left',
nameFormatter: null // 可以强制覆盖,手动设置label
},
tooltip: {
titleFormatter: null,
nameFormatter: null,
valueFormatter: null
},
column: true,
dodge: true,
dodgeStack: false,
stack: false,
stackReverse: true,
percentage: false,
marginRatio: 0,
grid: false,
zoom: false,
facet: false,
size: null,
label: false,
polar: false,
innerRadius: 0
};
};
_proto.init = function init(chart, config, data) {
var _config$legend, _config$legend2, _config$legend3, _config$legend4;
// 设置数据度量
var defs = {
x: (0, _common.propertyAssign)(_common.propertyMap.axis, {
// type: 'cat',
mask: 'auto'
}, config.xAxis),
y: (0, _common.propertyAssign)(_common.propertyMap.axis, {
nice: true,
type: 'linear',
tickCount: 5,
sync: 'y'
}, config.yAxis),
type: {
type: 'cat',
sync: true
},
facet: {
sync: true
},
sum: {
nice: true,
sync: 'y'
},
percent: (0, _common.propertyAssign)(_common.propertyMap.axis, {
nice: true,
type: 'linear',
tickCount: 5
}, config.yAxis)
};
(0, _autoTimeMask["default"])(defs, this.rawData);
chart.scale(defs);
var dataView = computerData(config, data);
this.barDataView = dataView;
if (config.percentage) {
chart.data(dataView.rows);
} else {
if (config.showStackSum) {
data.map(function (el) {
var filterData = dataView.rows.filter(function (row) {
return el.x === row.x && el.type === row.type;
});
if (filterData.length > 0) {
el.sum = filterData[0].sum;
}
});
}
chart.data(data);
}
chart.axis('sum', false); // 设置单个Y轴
if (!config.facet) {
if (config.percentage) {
(0, _rectYAxis["default"])(this, chart, config, 'percent');
} else {
(0, _rectYAxis["default"])(this, chart, config);
}
} // 设置X轴
(0, _rectXAxis["default"])(this, chart, config); // 需要保证原始数据传入的时候按分组顺序传入
// 这个是分组的顺序
var dodgeGroups = []; // 如果开启图例分组,先判定数据中有分组信息
var newItems = undefined; // 如果开启图例折叠,列表型则分组图例不适配
if (config !== null && config !== void 0 && (_config$legend = config.legend) !== null && _config$legend !== void 0 && _config$legend.dodge && !(config !== null && config !== void 0 && (_config$legend2 = config.legend) !== null && _config$legend2 !== void 0 && _config$legend2.foldable) && !(config !== null && config !== void 0 && (_config$legend3 = config.legend) !== null && _config$legend3 !== void 0 && _config$legend3.table)) {
var _this$rawData, _this$rawData2;
// 处理默认数据,按照分组顺序排列
newItems = [];
(_this$rawData = this.rawData) === null || _this$rawData === void 0 ? void 0 : _this$rawData.forEach(function (subData) {
var _newItems, _newItems$filter;
if ((subData !== null && subData !== void 0 && subData.dodge || subData !== null && subData !== void 0 && subData.facet) && ((_newItems = newItems) === null || _newItems === void 0 ? void 0 : (_newItems$filter = _newItems.filter(function (el) {
return (el.dodge || el.facet) === ((subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet));
})) === null || _newItems$filter === void 0 ? void 0 : _newItems$filter.length) == 0) {
dodgeGroups.push((subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet));
}
});
(_this$rawData2 = this.rawData) === null || _this$rawData2 === void 0 ? void 0 : _this$rawData2.sort(function (a, b) {
return dodgeGroups.indexOf((a === null || a === void 0 ? void 0 : a.dodge) || (a === null || a === void 0 ? void 0 : a.facet)) - dodgeGroups.indexOf((b === null || b === void 0 ? void 0 : b.dodge) || (b === null || b === void 0 ? void 0 : b.facet));
}).forEach(function (subData, index) {
var _newItems2, _newItems2$filter;
// 当Items里没有分组名称的时候,添加一个name为分组名称的item
if ((subData !== null && subData !== void 0 && subData.dodge || subData !== null && subData !== void 0 && subData.facet) && ((_newItems2 = newItems) === null || _newItems2 === void 0 ? void 0 : (_newItems2$filter = _newItems2.filter(function (el) {
return (el.dodge || el.facet) === ((subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet));
})) === null || _newItems2$filter === void 0 ? void 0 : _newItems2$filter.length) == 0) {
newItems.push({
id: (subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet),
name: ((subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet)) + ": ",
dodge: (subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet),
value: (subData === null || subData === void 0 ? void 0 : subData.dodge) || (subData === null || subData === void 0 ? void 0 : subData.facet),
marker: {
spacing: index !== 0 ? 24 : 0,
style: {
r: 0
}
}
});
}
var rawColor; // 函数暂时不做处理,和默认数组处理方式保持一致
if (typeof (config === null || config === void 0 ? void 0 : config.colors) === 'string') {
rawColor = config === null || config === void 0 ? void 0 : config.colors;
} else if (typeof (config === null || config === void 0 ? void 0 : config.colors) === 'object') {
var _config$colors;
rawColor = config === null || config === void 0 ? void 0 : (_config$colors = config.colors) === null || _config$colors === void 0 ? void 0 : _config$colors[index];
} else if (typeof (config === null || config === void 0 ? void 0 : config.colors) === 'function') {
rawColor = _index["default"].category_12[index];
}
newItems.push({
id: subData === null || subData === void 0 ? void 0 : subData.name,
name: subData === null || subData === void 0 ? void 0 : subData.name,
value: subData === null || subData === void 0 ? void 0 : subData.name,
marker: {
symbol: 'square',
spacing: 4,
style: {
r: 3,
fill: rawColor,
lineAppendWidth: 0,
fillOpacity: 1
}
},
unchecked: false
});
});
} else if (config !== null && config !== void 0 && (_config$legend4 = config.legend) !== null && _config$legend4 !== void 0 && _config$legend4.items) {
// 自定义优先级高于内置配置
newItems = config.legend.items;
} // 设置图例
(0, _rectLegend["default"])(this, chart, config, {
items: newItems
}, false, 'type');
(0, _legendFilter["default"])(this, chart); // tooltip
(0, _rectTooltip["default"])(this, chart, config, {}, null, {
showCrosshairs: false,
showMarkers: false
}); // 绘制辅助线,辅助背景区域
(0, _guide["default"])(chart, config); // 设置坐标系:极坐标/直角坐标
var chartCoord = config.polar ? chart.coordinate('polar', {
innerRadius: config.innerRadius || 0
}) : chart.coordinate(); // 横向柱状图
if (!config.column || typeof config.column === 'object') {
var columnConfig = typeof config.column === 'object' ? config.column : {};
chartCoord.transpose(); // 横向镜像
if (columnConfig.reflect) {
chartCoord.reflect('x');
}
} // // 玉玦图,需要手动添加 数据标记
// if (config.polar && !config.column && config.dataType !== 'g2') {
// this.rawData[0].data.forEach((d: any, i: number) => {
// let x = d.x;
// if (Array.isArray(d)) {
// x = d[0];
// } else if (
// config.xAxis &&
// config.xAxis.categories &&
// config.xAxis.categories[i]
// ) {
// x = config.xAxis.categories[i];
// // const y = isNaN(d) ? d[0] : d;
// }
//
// chart.annotation().text({
// position: [x, 0],
// // content: `${x}`,
// style: {
// fill: themes['widgets-axis-label'],
// textAlign: 'start',
// },
// });
// });
// }
if (config.facet) {
var facetConfig = typeof config.facet === 'object' ? config.facet : {};
var facetTitleConfig = (0, _common.merge)({
offsetX: (0, _common.pxToNumber)(_index["default"]['widgets-font-size-1']),
// 底层使用 view.annotation().text 绘制,可以使用 rotate 进行翻转
rotate: config.column ? Math.PI / 2 : undefined,
style: {
fontSize: (0, _common.pxToNumber)(_index["default"]['widgets-font-size-1']),
textAlign: 'center',
fill: _index["default"]['widgets-axis-label']
}
}, facetConfig.title || {});
var self = this;
chart.facet(facetConfig.type || 'mirror', {
fields: ['facet'],
transpose: facetConfig.transpose || !config.column,
padding: facetConfig.padding,
spacing: facetConfig.spacing || (config.column ? [0, 18] : [32, 0]),
showTitle: typeof facetConfig.showTitle === 'boolean' ? facetConfig.showTitle : true,
title: facetTitleConfig,
eachView: function eachView(view, facet) {
var yAxisCustomConfig = null; // 为 labelFormatter 的第二个参数添加分面信息
if (config.yAxis && config.yAxis.visible !== false) {
var _ref = config.yAxis || {},
labelFormatter = _ref.labelFormatter;
if (labelFormatter) {
yAxisCustomConfig = {
label: {
formatter: function formatter(text, item, index) {
return labelFormatter(text, (0, _extends2["default"])({
facet: facet.colValue || facet.rowValue
}, item), index);
}
}
};
}
}
(0, _rectYAxis["default"])(self, view, config, 'y', yAxisCustomConfig); // Tooltip 背景区域
(0, _interaction.activeRegionWithTheme)(view);
drawBar(view, config, config.colors, facet);
}
});
} else {
if (!config.polar) {
// Tooltip 背景区域
(0, _interaction.activeRegionWithTheme)(chart);
}
drawBar(chart, config, config.colors);
}
(0, _rectZoom["default"])(chart, config, (0, _ChartProvider.getText)('reset', this.language || this.context.language, this.context.locale)); // 缩略轴
(0, _rectSlider["default"])(chart, config); // 滚动条
(0, _rectScrollbar["default"])(chart, config); // 判断是否要加padding
// 当开启label、label在柱子上方、legend不在上方,且存在某根柱子数值与y轴最大值接近时需要加padding
// 极坐标柱状图不考虑,分面自己加padding,此处不处理
chart.on('beforepaint', function () {
var _chart$geometries, _chart$geometries$, _chart$geometries$$sc, _chart$geometries$$sc2, _chart$coordinateBBox, _config$label, _config$label2, _config$label3, _config$legend5, _config$legend6, _config$legend7;
// y轴刻度最大值
var axisMax = chart === null || chart === void 0 ? void 0 : (_chart$geometries = chart.geometries) === null || _chart$geometries === void 0 ? void 0 : (_chart$geometries$ = _chart$geometries[0]) === null || _chart$geometries$ === void 0 ? void 0 : (_chart$geometries$$sc = _chart$geometries$.scales) === null || _chart$geometries$$sc === void 0 ? void 0 : (_chart$geometries$$sc2 = _chart$geometries$$sc.y) === null || _chart$geometries$$sc2 === void 0 ? void 0 : _chart$geometries$$sc2.max; // y轴高度
var height = chart === null || chart === void 0 ? void 0 : (_chart$coordinateBBox = chart.coordinateBBox) === null || _chart$coordinateBBox === void 0 ? void 0 : _chart$coordinateBBox.height; // 是否显示label,且label在top
var showLabel = (config === null || config === void 0 ? void 0 : config.label) === true || typeof (config === null || config === void 0 ? void 0 : config.label) === 'object' && (config === null || config === void 0 ? void 0 : (_config$label = config.label) === null || _config$label === void 0 ? void 0 : _config$label.visible) !== false && ((config === null || config === void 0 ? void 0 : (_config$label2 = config.label) === null || _config$label2 === void 0 ? void 0 : _config$label2.position) === undefined || (config === null || config === void 0 ? void 0 : (_config$label3 = config.label) === null || _config$label3 === void 0 ? void 0 : _config$label3.position) === 'top'); // 是否隐藏legend,或legend不在top
var hideLegend = (config === null || config === void 0 ? void 0 : config.legend) === false || typeof (config === null || config === void 0 ? void 0 : config.legend) === 'object' && ((config === null || config === void 0 ? void 0 : (_config$legend5 = config.legend) === null || _config$legend5 === void 0 ? void 0 : _config$legend5.visible) === false || (config === null || config === void 0 ? void 0 : (_config$legend6 = config.legend) === null || _config$legend6 === void 0 ? void 0 : _config$legend6.position) && (config === null || config === void 0 ? void 0 : (_config$legend7 = config.legend) === null || _config$legend7 === void 0 ? void 0 : _config$legend7.position) !== 'top');
if (!(config !== null && config !== void 0 && config.appendPadding) && showLabel && hideLegend && !(config !== null && config !== void 0 && config.polar) && !(config !== null && config !== void 0 && config.facet)) {
var addPadding = false; // 横向柱图默认加padding
if ((config === null || config === void 0 ? void 0 : config.column) === false || typeof (config === null || config === void 0 ? void 0 : config.column) === 'object') {
addPadding = true;
} else if ((config !== null && config !== void 0 && config.dodgeStack || config !== null && config !== void 0 && config.stack) && config !== null && config !== void 0 && config.percentage) {
// 百分比堆叠默认加padding
addPadding = true;
} else {
var valueMap = {};
(data || []).forEach(function (d) {
var xValue = d.x + "-" + (config !== null && config !== void 0 && config.stack ? '' : d.dodge || d.type);
if (!(xValue in valueMap)) {
valueMap[xValue] = 0;
} // 区间柱状图
if (Array.isArray(d.y)) {
var _d$y;
valueMap[xValue] += ((_d$y = d.y) === null || _d$y === void 0 ? void 0 : _d$y[1]) || 0;
} else {
// 堆叠、分组堆叠、普通柱图
valueMap[xValue] += d.y;
}
});
var maxY = Math.max.apply(Math, Object.values(valueMap)); // 判断最高的柱子距离顶部的间距是否过小
var dis = (1 - maxY / axisMax) * height;
if (dis < 20) {
addPadding = true;
}
}
if (addPadding) {
chart.appendPadding = [20, 0, 0, 0];
} else {
chart.appendPadding = undefined;
}
}
});
};
_proto.changeData = function changeData(chart, config, data) {
var _this2 = this;
// 分面需要对数据进行筛选处理
if (config.facet) {
chart.views.forEach(function (subView, idx) {
var _chart$facetInstance, _facetInstance$idx, _facetInstance$idx2;
// 目前想到每个视图获取对应的分面数据的情况通过分面的实例进行获取,后面看有没有更好的情况
var facetInstance = chart === null || chart === void 0 ? void 0 : (_chart$facetInstance = chart.facetInstance) === null || _chart$facetInstance === void 0 ? void 0 : _chart$facetInstance.facets;
var facetValue = !config.column || typeof config.column === 'object' ? facetInstance === null || facetInstance === void 0 ? void 0 : (_facetInstance$idx = facetInstance[idx]) === null || _facetInstance$idx === void 0 ? void 0 : _facetInstance$idx.columnValue : facetInstance === null || facetInstance === void 0 ? void 0 : (_facetInstance$idx2 = facetInstance[idx]) === null || _facetInstance$idx2 === void 0 ? void 0 : _facetInstance$idx2.rowValue;
var facetData = data === null || data === void 0 ? void 0 : data.filter(function (el) {
return el.facet === facetValue;
});
subView.changeData(facetData);
});
} else if (config.percentage && this.barDataView) {
this.barDataView.source(data);
chart.changeData(this.barDataView.rows);
} else {
if (config.showStackSum) {
data.map(function (el) {
var filterData = _this2.barDataView.rows.filter(function (row) {
return el.x === row.x && el.type === row.type;
});
if (filterData.length > 0) {
el.sum = filterData[0].sum;
}
});
}
chart.changeData(data);
}
};
return Bar;
}(_Base2["default"]);
exports.Bar = Bar;
var Wbar = (0, _errorWrap["default"])(Bar);
var _default = Wbar; // export default errorWrap(Wbar);
exports["default"] = _default;
function drawBar(chart, config, colors, facet) {
var stack = config.stack,
stackReverse = config.stackReverse,
marginRatio = config.marginRatio,
dodge = config.dodge,
dodgeStack = config.dodgeStack,
percentage = config.percentage,
size = config.size,
minSize = config.minSize,
_config$maxSize = config.maxSize,
maxSize = _config$maxSize === void 0 ? 24 : _config$maxSize,
columnWidthRatio = config.columnWidthRatio,
dodgePadding = config.dodgePadding;
var geomConfig = {
minColumnWidth: minSize || null,
maxColumnWidth: maxSize || null,
columnWidthRatio: columnWidthRatio || null,
dodgePadding: dodgePadding || null
};
var geom = chart.interval(geomConfig).position(['x', 'y']).color('type', colors);
if (percentage) {
geom = geom.position(['x', 'percent']);
}
if (dodgeStack) {
geom = geom.adjust([{
type: 'dodge',
marginRatio: marginRatio || 0,
// 数值范围为 0 至 1,用于调整分组中各个柱子的间距
dodgeBy: 'dodge'
}, {
type: 'stack',
reverseOrder: !stackReverse // 层叠顺序倒序
}]);
} else if (stack) {
// 堆叠
geom = geom.adjust([{
type: 'stack',
reverseOrder: !stackReverse // 层叠顺序倒序
}]);
} else if (dodge) {
// 分组
geom = geom.adjust([{
type: 'dodge',
marginRatio: marginRatio || 0 // 数值范围为 0 至 1,用于调整分组中各个柱子的间距
}]);
}
if (typeof config.animate === 'object') {
geom.animate(config.animate);
}
(0, _geomSize["default"])(geom, size, null, 'y', 'x*y*type*facet*extra');
(0, _geomStyle["default"])(geom, config.geomStyle, {}, 'x*y*type*facet*extra'); // TOPO 图表类型的规则执行,以及API制定
// 【API执行】堆叠/分组堆叠/百分比堆叠的时候,开启label内置增加优化显示,已配置的业务关闭
if (config.showStackSum && config.stack) {
var labelGeom = chart.interval({}).position(['x', 'sum']).adjust([{
type: 'stack',
reverseOrder: !stackReverse
}]).tooltip(false).size(0).style({
opacity: 0,
r: 0
});
labelGeom.label('sum');
} else {
(0, _label["default"])({
geom: geom,
config: config,
extraCallbackParams: facet ? [facet] : undefined
});
}
}
function computerData(config, data) {
var stack = config.stack,
dodgeStack = config.dodgeStack,
percentage = config.percentage;
var dv = new _view.View().source(data);
if (percentage && dodgeStack) {
dv.transform({
type: 'percent',
field: 'y',
dimension: 'type',
groupBy: ['x', 'dodge'],
as: 'percent'
});
} else if (percentage) {
dv.transform({
type: 'percent',
field: 'y',
dimension: 'type',
groupBy: ['x'],
as: 'percent'
});
} else if (stack) {
// 只算第一组的数据总量
// 按X轴计算Y的总量,映射到sum字段上
dv.transform({
type: 'aggregate',
fields: ['y'],
operations: ['sum'],
as: ['sum'],
groupBy: ['x']
});
}
return dv;
}