@alicloud/cloud-charts
Version:

724 lines (668 loc) • 23.9 kB
JavaScript
;
import _extends from "@babel/runtime/helpers/extends";
import { customFormatter, merge } from './common';
import themes from '../themes';
import { pxToNumber } from './common';
import { warn } from './log';
import { registerAction } from '@antv/g2/esm';
import { ListChecked, ListReverseChecked } from './interaction'; // import { legendHtmlContainer, legendHtmlList, legendHtmlListItem, legendHtmlMarker, legendTextStyle } from './g2Theme';
/*
* 提取渐变色中的第一个颜色,具体逻辑来自 G2 内部
* */
// // const regexTags = /[MLHVQTCSAZ]([^MLHVQTCSAZ]*)/ig;
// // const regexDot = /[^\s\,]+/ig;
// const regexLG = /^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i;
// const regexRG = /^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i;
// // const regexPR = /^p\s*\(\s*([axyn])\s*\)\s*(.*)/i;
// const regexColorStop = /[\d.]+:(#[^\s]+|[^\)]+\))/ig;
//
// // 取匹配出来的第一个颜色
// function getFirstStop(steps) {
// return steps.match(regexColorStop)[0].split(':')[1];
// }
// function getColor(color) {
// if (color[1] === '(' || color[2] === '(') {
// if (color[0] === 'l') {
// // 线性 regexLG.test(color)
// return getFirstStop(regexLG.exec(color)[2]);
// } else if (color[0] === 'r') {
// // 径向 regexRG.test(color)
// return getFirstStop(regexRG.exec(color)[4]);
// } else if (color[0] === 'p') {
// // regexPR.test(color)
// // return parsePattern(color, self, context);
// }
// }
// return color;
// }
function getPosition(position, align) {
var _position$split = position.split('-'),
p = _position$split[0],
a = _position$split[1];
if (!a) {
if (!align || align === 'center') {
return p;
} else {
return p + "-" + align;
}
}
return position;
}
function getPadding(position, base, userPadding, isPolar) {
if (userPadding) {
return userPadding;
}
var len = base * 4 / 3;
var lrLen = base * 2;
var _position$split2 = position.split('-'),
p = _position$split2[0];
switch (p) {
case 'bottom':
return [len, 0, 0, 0];
case 'left':
if (isPolar === true) {
return [0, lrLen, 0, 0];
}
return [0, len, 0, 0];
case 'top':
return [0, 0, len, 0];
case 'right':
if (isPolar === true) {
return [0, 0, 0, lrLen];
}
return [0, 0, 0, len];
}
return [len, len, len, len];
}
/**
* rectLegend 直角坐标系legend配置。
*
* @param {this} ctx 组件实例 this 指针
* @param {Chart} chart 图表实例
* @param {Object} config 配置项
* @param {Object} defaultConfig 组件的自定义配置
* @param {boolean} isOneDataGroup 数据是否为单组形式,类似饼图和漏斗图
* @param {string} field 数据映射字段
* @param {boolean} isPolar 是否极坐标系
* @param {function} itemFormatter 组件自定义的 item 格式函数
* */
export default function (ctx, chart, config, defaultConfig, isOneDataGroup, field, isPolar, itemFormatter) {
// 设置图例
if (config.legend === false || config.legend && typeof config.legend !== 'boolean' && config.legend.visible === false) {
chart.legend(false);
} else {
var _ref = config.legend === true ? {} : config.legend || {},
_ref$autoCollapse = _ref.autoCollapse,
autoCollapse = _ref$autoCollapse === void 0 ? true : _ref$autoCollapse,
collapseRow = _ref.collapseRow,
_ref$position = _ref.position,
position = _ref$position === void 0 ? 'bottom' : _ref$position,
_ref$align = _ref.align,
align = _ref$align === void 0 ? 'left' : _ref$align,
padding = _ref.padding,
_nameFormatter = _ref.nameFormatter,
_valueFormatter = _ref.valueFormatter,
showData = _ref.showData,
marker = _ref.marker,
_ref$allowAllCanceled = _ref.allowAllCanceled,
allowAllCanceled = _ref$allowAllCanceled === void 0 ? false : _ref$allowAllCanceled,
_ref$hoverable = _ref.hoverable,
hoverable = _ref$hoverable === void 0 ? true : _ref$hoverable,
onHover = _ref.onHover,
_ref$clickable = _ref.clickable,
clickable = _ref$clickable === void 0 ? true : _ref$clickable,
onClick = _ref.onClick,
defaultClickBehavior = _ref.defaultClickBehavior,
customConfig = _ref.customConfig,
maxWidth = _ref.maxWidth,
maxHeight = _ref.maxHeight,
maxWidthRatio = _ref.maxWidthRatio,
maxHeightRatio = _ref.maxHeightRatio,
_ref$useReverseChecke = _ref.useReverseChecked,
useReverseChecked = _ref$useReverseChecke === void 0 ? true : _ref$useReverseChecke,
table = _ref.table,
_ref$foldable = _ref.foldable,
foldable = _ref$foldable === void 0 ? false : _ref$foldable;
var baseFontSizeNum = pxToNumber(themes['widgets-font-size-1']);
var legendConfig = _extends({}, defaultConfig, {
position: getPosition(position, align),
flipPage: autoCollapse,
maxRow: collapseRow,
itemName: {
// formatter: nameFormatter,
formatter: function formatter(text, item, index) {
// if (text === 'widgets-pad-type') {
// return '';
// }
if (text.startsWith('undefined-name-')) {
return '';
}
if (_nameFormatter) {
return _nameFormatter(text, itemFormatter ? itemFormatter(item, index) : item, index);
}
return text;
}
},
// background: {
// padding: 0,
// },
padding: getPadding(position, baseFontSizeNum, padding, isPolar),
marker: marker || {
// symbol: 'circle',
style: {
r: baseFontSizeNum / 4,
// fill: styleSheet.legendMarkerColor,
// lineCap: 'butt',
lineAppendWidth: 0,
fillOpacity: 1
}
},
maxWidth: maxWidth,
maxHeight: maxHeight,
maxWidthRatio: maxWidthRatio || 0.45,
maxHeightRatio: maxHeightRatio || 0.45,
table: table,
foldable: foldable,
valueFormatter: _valueFormatter
}); // legend hover 相关事件
// 移除默认交互
chart.removeInteraction('legend-active');
if (hoverable) {
// 复写高亮交互, 点击图例后高亮重置
chart.interaction('legend-highlight', {
start: [{
trigger: 'legend-item:mouseenter',
action: ['list-highlight:highlight', 'element-highlight:highlight'],
isEnable: function isEnable(ctx) {
// @ts-ignore
var _ref2 = ctx.getAction('list-highlight').getTriggerListInfo() || {},
item = _ref2.item,
list = _ref2.list; // 分组的item不触发任何交互
if (!item || !!item.dodge) {
return false;
}
return true;
}
}],
end: [{
trigger: 'legend-item:mouseleave',
action: ['list-highlight:reset', 'element-highlight:reset']
}, {
trigger: 'legend-item:click',
action: ['list-highlight:reset', 'element-highlight:reset']
}]
});
}
if (onHover) {
warn('config.legend', "onHover \u5C5E\u6027\u5DF2\u5E9F\u5F03\uFF0C\u8BF7\u4F7F\u7528\u901A\u7528\u4E8B\u4EF6\u65B9\u6CD5 props.event = { 'legend-item:mouseenter': onHover }");
chart.on('legend-item:mouseenter', onHover);
} // legend click 事件
// 去除默认图例行为
chart.removeInteraction('legend-filter'); // 如果用内置堆叠图显示label,则不会触发图例点击效果
if (!config.showStackSum) {
if (useReverseChecked) {
// 默认反选模式
registerAction('list-checked', ListReverseChecked);
if (clickable) {
if (allowAllCanceled) {
chart.interaction('legend-custom-filter');
} else {
chart.interaction('legend-custom-filter-last');
}
}
} else {
registerAction('list-checked', ListChecked);
if (clickable) {
if (allowAllCanceled) {
chart.interaction('legend-custom-filter');
} else {
chart.interaction('legend-singlechecked-filter-last');
}
}
}
}
if (onClick) {
warn('config.legend', "onClick \u5C5E\u6027\u5DF2\u5E9F\u5F03\uFF0C\u8BF7\u4F7F\u7528\u901A\u7528\u4E8B\u4EF6\u65B9\u6CD5 props.event = { 'legend-item:click': onClick }");
chart.on('legend-item:click', onClick);
}
if (defaultClickBehavior !== undefined) {
warn('config.legend', "defaultClickBehavior \u5C5E\u6027\u5DF2\u5E9F\u5F03\uFF0C\u53D6\u6D88\u9ED8\u8BA4\u70B9\u51FB\u6548\u679C\u53EA\u9700\u8981\u5173\u95ED legend.clickable \u5373\u53EF");
}
if (showData) {
var customValueFormatter = customFormatter(config.legend === true ? {} : config.legend || {});
legendConfig.itemValue = {
style: {
fill: themes['widgets-legend-text'],
fontSize: baseFontSizeNum,
lineHeight: baseFontSizeNum,
fontFamily: themes['widgets-font-family-txd-m-number']
},
formatter: function formatter(text, item, index) {
// console.log(222, text, item, index)
// @ts-ignore
var value = getLastValue(item.name, ctx.rawData, isOneDataGroup);
if (_valueFormatter) {
return _valueFormatter(value, itemFormatter ? itemFormatter(item, index) : item, index);
} else if (customValueFormatter) {
return customValueFormatter(value);
}
return value;
}
};
} // // 因为图例项有下边距,所以bottom设置为0即可
// const legendStyle = Object.assign({}, legendHtmlContainer);
// const legendItemStyle = Object.assign({}, legendHtmlListItem);
// if (position === 'bottom') {
// legendStyle.bottom = 0;
// legendStyle.overflow = 'visible';
// // 置于下方时设置margin top
// legendItemStyle.marginBottom = 0;
// legendItemStyle.marginTop = themes['widgets-font-size-1']
// } else {
// legendStyle.top = 0;
// }
// if (align === 'right') {
// legendStyle.right = 0;
// legendStyle.textAlign = 'right';
// } else if (align === 'left') {
// legendStyle.left = 0;
// } else if (align === 'center') {
// legendStyle.left = 0;
// legendStyle.width = '100%';
// legendStyle.textAlign = 'center';
// } else {
// // 默认放到左边
// legendStyle.left = 0;
// }
//
// const legendConfig = {
// // 这些是widgets特有的属性
// autoCollapse,
// collapseRow,
// // 以下为g2的属性
// useHtml: true,
// title: null,
// position: position || 'top',
// allowAllCanceled,
// // 这个属性文档里没有,设置为false可以让图例不居中,再手动设置定位样式
// autoPosition: false,
// hoverable,
// onHover,
// clickable,
// onClick,
// // 隐藏属性,设置了 onClick 时依然保留默认点击行为
// defaultClickHandlerEnabled: defaultClickBehavior,
// itemTpl: (value, color, checked, index) => {
// const item = getRawData(config, this.rawData, value, isOneDataGroup);
//
// const newName = nameFormatter ? nameFormatter(value, {
// ...item,
// color,
// checked,
// }, index) : value;
//
// if (showData) {
// const dataValue = getDataValue(item.data);
// const newValue = valueFormatter ? valueFormatter(dataValue, {
// ...item,
// color,
// checked,
// }, index) : dataValue;
//
// return `${'<li class="g2-legend-list-item item-{index} {checked}" data-color="{originColor}" data-value="{originValue}">' +
// `<i class="g2-legend-marker" style="background-color:${getColor(color)};"></i>` +
// '<span class="g2-legend-text">'}${newName}</span><span class="g2-legend-value">${newValue}</span></li>`;
// }
//
// return `${'<li class="g2-legend-list-item item-{index} {checked}" data-color="{originColor}" data-value="{originValue}">' +
// `<i class="g2-legend-marker" style="background-color:${getColor(color)};"></i>` +
// '<span class="g2-legend-text">'}${newName}</span></li>`;
// },
// 'g2-legend': legendStyle,
// 'g2-legend-list': Object.assign({}, legendHtmlList),
// 'g2-legend-list-item': legendItemStyle,
// 'g2-legend-marker': Object.assign({}, legendHtmlMarker),
// textStyle: Object.assign({}, legendTextStyle),
// };
// if (componentConfig) {
// // 内部的componentConfig直接使用assign浅复制,方便覆盖。
// Object.assign(legendConfig, componentConfig);
// }
if (customConfig) {
merge(legendConfig, customConfig);
} // if (legendConfig['g2-legend'] && typeof legendConfig['g2-legend'] === 'object') {
// Object.keys(style).forEach((key) => {
// // 确保每一项有值设置了,如果是假值则忽略
// if (style[key]) {
// // hack 字号转化为 px
// if (key === 'fontSize' && !isInvalidNumber(style[key])) {
// legendConfig['g2-legend'][key] = `${style[key]}px`;
// } else {
// legendConfig['g2-legend'][key] = style[key];
// }
// // fix: 新版G2后,图例文字颜色的设置需要注入 textStyle 中才能生效。
// if (key === 'color' && legendConfig.textStyle && typeof legendConfig.textStyle === 'object') {
// legendConfig.textStyle.fill = style[key];
// }
// }
// });
// // Object.assign(legendConfig['g2-legend'], style);
// }
if (field) {
// fix: 修复 legend 设置了 field 后,内部 options 变为 { [field]: options },无法读取 onClick 的问题
// if (onClick) {
// chart.legend({
// onClick,
// // 隐藏属性,设置了 onClick 时依然保留默认点击行为
// defaultClickHandlerEnabled: defaultClickBehavior,
// });
// }
chart.legend(field, legendConfig);
} else {
chart.legend(legendConfig);
} // if (this.afterRenderCallbacks && legendConfig.autoCollapse) {
// const legendCollapseInfo = legendCollapse.call(this, legendConfig);
// this.afterRenderCallbacks.push(legendCollapseInfo.render);
//
// if (this.unmountCallbacks) {
// this.unmountCallbacks.push(legendCollapseInfo.unmount);
// }
// }
}
}
function getLastValue(name, rawData, isOneDataGroup) {
var dataGroup = getItemData(name, rawData, isOneDataGroup);
if (!dataGroup) {
return '';
}
if (isOneDataGroup) {
if (Array.isArray(dataGroup)) {
return dataGroup[1];
}
if (typeof dataGroup === 'object') {
return dataGroup.y;
}
} else if (!Array.isArray(dataGroup) && Array.isArray(dataGroup.data)) {
var len = dataGroup.data.length;
var lastItem = dataGroup.data[len - 1];
if (Array.isArray(lastItem)) {
return lastItem[1];
}
if (typeof lastItem === 'object') {
return lastItem.y;
}
}
return '';
}
function getItemData(name, rawData, isOneDataGroup) {
if (!rawData) {
return undefined;
}
if (isOneDataGroup) {
var _originData = rawData[0];
var result = undefined;
_originData && _originData.data.some(function (r) {
if (Array.isArray(r) && r[0] === name || typeof r === 'object' && r.x === name) {
result = r;
return true;
}
return false;
}); // if (Array.isArray(result)) {
// result = {
// data: result,
// };
// }
return result;
}
var originData = undefined;
rawData.some(function (r) {
if (r.data && r.name === name) {
originData = r;
return true;
}
return false;
});
return originData;
} // function getRawData(config, rawData, name, isOneDataGroup) {
// if (!rawData) {
// return {};
// }
//
// if (isOneDataGroup) {
// const originData = rawData[0] || {};
// let result = {};
//
// originData.data.some((r) => {
// if ((Array.isArray(r) && r[0] === name) || (typeof r === 'object' && r.x === name)) {
// result = r;
// return true;
// }
// return false;
// });
//
// if (Array.isArray(result)) {
// result = {
// data: result,
// };
// }
//
// return result;
// }
//
// let originData = {};
// if (config.dataType !== 'g2') {
// rawData.some((r) => {
// if (r.name === name) {
// originData = r;
// return true;
// }
// return false;
// });
// }
//
// return originData;
// }
//
// function getDataValue(data) {
// if (!Array.isArray(data)) {
// return '-';
// }
//
// for (let i = 0; i < data.length; i++) {
// // 单组数据时,如饼图/漏斗图,data[i] 不是数组/对象
// if (typeof data[i] !== 'object' && i === 1) {
// return data[i];
// }
// if (i === data.length - 1) {
// if (Array.isArray(data[i])) {
// return data[i][1];
// }
// if (typeof data[i] === 'object') {
// return data[i].y;
// }
// }
// }
// }
//
// function legendCollapse(legendConfig) {
// let { collapseRow = 2 } = legendConfig;
// let collapseInstance = null;
// return {
// render(chart, config) {
// if (config.legend !== false && this.chartDom) {
// const legendWrapperDom = this.chartDom.querySelector('.g2-legend');
// const legendListDom = this.chartDom.querySelector('.g2-legend-list');
// const legendListItemDom = this.chartDom.querySelector('.g2-legend-list-item');
//
// if (!legendWrapperDom || !legendListDom || !legendListItemDom) {
// return;
// }
//
// const itemStyle = window.getComputedStyle(legendListItemDom);
// const marginTop = pxToNumber(itemStyle.getPropertyValue('margin-top'));
// const marginBottom = pxToNumber(itemStyle.getPropertyValue('margin-bottom'));
// const itemHeight = legendListItemDom.offsetHeight + marginTop + marginBottom;
// const wrapperHeight = legendWrapperDom.offsetHeight;
//
// // 自动适配图例折叠高度
// if (collapseRow === 'auto') {
// const chartHeight = this._size && this._size[1];
// if (chartHeight) {
// // 行数最多占图表高度的三分之一,最小为2。
// collapseRow = Math.max(2, Math.round((chartHeight / itemHeight) / 3));
// }
// } else {
// collapseRow = Number(collapseRow);
// }
//
// if (wrapperHeight > itemHeight * collapseRow) {
// if (!collapseInstance) {
// collapseInstance = new Collapse(legendWrapperDom, legendListDom, {
// wrapperHeight,
// itemHeight,
// collapseRow,
// collapseTop: marginTop,
// collapseBottom: marginBottom,
// });
// } else if (collapseInstance.dom !== legendWrapperDom || collapseInstance.listDom !== legendListDom) {
// // 重新渲染后,dom节点可能已经改变,销毁重建
// collapseInstance.destroy();
//
// collapseInstance = new Collapse(legendWrapperDom, legendListDom, {
// wrapperHeight,
// itemHeight,
// collapseRow,
// collapseTop: marginTop,
// collapseBottom: marginBottom,
// });
// }
//
// collapseInstance.start({ collapseRow });
// } else if (collapseInstance) {
// collapseInstance.end();
// }
// }
// },
// unmount() {
// if (collapseInstance) {
// collapseInstance.destroy();
// }
// },
// };
// }
//
// class Collapse {
// constructor(dom, listDom, config) {
// this.dom = dom;
// this.listDom = listDom;
// this.moveOffset = 0;
// this.config = config;
// this.handleClick = this.handleClick.bind(this);
//
// const { itemHeight, collapseRow, wrapperHeight, collapseTop, collapseBottom } = this.config;
//
// const collapseDom = document.createElement('div');
// collapseDom.className = 'widgets-legend-collapse';
// collapseDom.style.paddingTop = `${collapseTop}px`;
// collapseDom.style.paddingBottom = `${collapseBottom}px`;
// this.collapseDom = collapseDom;
//
// const collapseUpDom = document.createElement('div');
// collapseUpDom.className = 'legend-collapse-btn collapse-up';
// this.collapseUpDom = collapseUpDom;
// const collapseDownDom = document.createElement('div');
// collapseDownDom.className = 'legend-collapse-btn collapse-down';
// this.collapseDownDom = collapseDownDom;
// collapseDom.appendChild(collapseUpDom);
// collapseDom.appendChild(collapseDownDom);
//
// collapseDom.addEventListener('click', this.handleClick);
// collapseDom.addEventListener('mousemove', noopEvent);
// collapseDom.addEventListener('mouseout', noopEvent);
//
// this.minOffset = -(wrapperHeight / itemHeight) + collapseRow;
// this.maxOffset = 0;
// }
//
// handleClick(e) {
// e.stopPropagation();
//
// if (!e.target.classList.contains('legend-collapse-btn') || e.target.classList.contains('disable')) {
// return;
// }
//
// let { moveOffset } = this;
//
// // 上一页
// if (e.target.classList.contains('collapse-up')) {
// moveOffset += 1;
// }
// // 下一页
// if (e.target.classList.contains('collapse-down')) {
// moveOffset -= 1;
// }
//
// this.moveOffset = moveOffset;
//
// this.renderState();
// }
//
// renderState() {
// const { itemHeight } = this.config;
//
// this.collapseUpDom.classList.remove('disable');
// this.collapseDownDom.classList.remove('disable');
//
// // 不能向下
// if (this.moveOffset <= this.minOffset) {
// this.moveOffset = this.minOffset;
// this.collapseDownDom.classList.add('disable');
// }
//
// // 不能向上
// if (this.moveOffset >= this.maxOffset) {
// this.moveOffset = this.maxOffset;
// this.collapseUpDom.classList.add('disable');
// }
//
// this.listDom.style.transform = `translate(0, ${this.moveOffset * itemHeight}px)`;
// }
//
// start({ collapseRow: newCollapseRow }) {
// const { itemHeight, collapseRow: oldCollapseRow } = this.config;
// const collapseRow = newCollapseRow || oldCollapseRow;
//
// this.dom.classList.add('has-collapse');
//
// // 展示时重新获取高度
// // 修复因样式变化导致滚动范围改变所引起的问题。
// this.config.wrapperHeight = this.dom.offsetHeight;
// this.minOffset = -(this.config.wrapperHeight / itemHeight) + collapseRow;
//
// this.dom.style.maxHeight = `${itemHeight * collapseRow}px`;
// this.dom.appendChild(this.collapseDom);
//
// this.renderState();
// }
//
// end() {
// this.dom.classList.remove('has-collapse');
// this.dom.style.maxHeight = '';
// // dom被g2重新渲染后已经不在原来的树中,需要额外判断
// if (this.collapseDom.parentNode === this.dom) {
// this.dom.removeChild(this.collapseDom);
// }
// }
//
// destroy() {
// this.end();
//
// this.collapseDom.removeEventListener('click', this.handleClick);
// this.collapseDom.removeEventListener('mousemove', noopEvent);
// this.collapseDom.removeEventListener('mouseout', noopEvent);
// }
// }
//
// function noopEvent(e) {
// e.stopPropagation();
// }