UNPKG

@alicloud/cloud-charts

Version:

![](https://img.shields.io/npm/v/@alicloud/cloud-charts?color=%23ff8200)

475 lines (458 loc) 19.9 kB
'use strict'; import _extends from "@babel/runtime/helpers/extends"; import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose"; import React from 'react'; import Base from '../common/Base'; import themes from '../themes/index'; import { /*pxToNumber,*/numberDecimal /*isInvalidNumber*/, customFormatter } from '../common/common'; import "./index.css"; import rectTooltip from '../common/rectTooltip'; import rectLegend from '../common/rectLegend'; import label from '../common/label'; import geomStyle from '../common/geomStyle'; import circleAnnotation from '../common/circleAnnoation'; import polarLegendLayout from '../common/polarLegendLayout'; import errorWrap from '../common/errorWrap'; import updateChildrenPosition from '../common/updateChildrenPosition'; import ReactDOM from 'react-dom'; import { FullCrossName } from '../constants'; import Wnumber from '../Wnumber'; // function transformCoord(coord, transform = {}) { // const { type, param } = transform; // if (coord[type] && Array.isArray(param)) { // coord[type](...param); // } // } // function selectGeom(geom, selectKey) { // if (!geom || !selectKey || !Array.isArray(this.data)) { if (!geom) { return; } geom.elements.forEach(function (element) { // 清除选中效果 if (element.hasState('selected')) { element.setState('selected', false); } // 如果selectKey为假值,则只清空选中效果。 if (!selectKey) { return; } var d = element.getData(); if (d.x === selectKey) { element.setState('selected', true); } }); } // // function paddingNumber(value) { // return isInvalidNumber(value) ? 0 : Number(value); // } // // export function getDrawPadding(drawPadding, labelConfig, defaultDrawPadding) { // if (Array.isArray(drawPadding)) { // return drawPadding; // } else if (!isInvalidNumber(drawPadding)) { // return [drawPadding, drawPadding, drawPadding, drawPadding]; // } else if (labelConfig && labelConfig.visible !== false) { // // 饼图使用 label 时,调整 drawPadding // return defaultDrawPadding.map(p => Math.max(p, 48)); // } else { // return defaultDrawPadding; // } // } export var Pie = /*#__PURE__*/function (_Base) { _inheritsLoose(Pie, _Base); function Pie() { 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 = 'G2Pie'; _this.legendField = 'x'; _this.totalData = 0; _this.sourceData = []; _this.geom = null; _this.noDataShape = null; return _this; } var _proto = Pie.prototype; _proto.getDefaultConfig = function getDefaultConfig() { return { colors: themes.category_12, // padding: [20, 20, 20, 20], legend: { position: 'right', // foldable: true, align: '', showData: true, nameFormatter: null, // 可以强制覆盖,手动设置label valueFormatter: null }, tooltip: { nameFormatter: null, valueFormatter: null }, // coord: null, autoSort: true, cycle: false, select: true, innerRadius: 0.8, // 内环半径大小,仅cycle为true时可用 outerRadius: 0.8, // 饼图半径大小,初始化时可用 // drawPadding: [10, 10, 10, 10], label: false, // 过滤负数 filterNegativeNumbers: true }; }; _proto.changeData = function changeData(chart, config, data) { // 更新数据总和值,保证百分比的正常 var totalData = 0; data.forEach(function (d) { totalData += d.y; }); this.totalData = totalData; this.sourceData = data; // 不要忘记排序的状态 if (config.autoSort) { data.sort(function (a, b) { return b.y - a.y; }); } chart.changeData(data); // 环图中心内容 if (config.cycle && config.innerContent && !this.props.children && !this.props.loading && !this.props.errorInfo) { var _this$chartDom$getEle, _config$innerContent$, _config$innerContent, _this$rawData, _this$rawData$, _config$innerContent$2, _config$innerContent2, _config$innerContent$3, _config$innerContent3; var container = (_this$chartDom$getEle = this.chartDom.getElementsByClassName(FullCrossName + "-children")) === null || _this$chartDom$getEle === void 0 ? void 0 : _this$chartDom$getEle[0]; if (!container) { container = document.createElement('div'); container.className = FullCrossName + "-children"; var firstChild = this.chartDom.firstChild; this.chartDom.insertBefore(container, firstChild); } var content = /*#__PURE__*/React.createElement(Wnumber, { bottomTitle: (_config$innerContent$ = config === null || config === void 0 ? void 0 : (_config$innerContent = config.innerContent) === null || _config$innerContent === void 0 ? void 0 : _config$innerContent.title) !== null && _config$innerContent$ !== void 0 ? _config$innerContent$ : (_this$rawData = this.rawData) === null || _this$rawData === void 0 ? void 0 : (_this$rawData$ = _this$rawData[0]) === null || _this$rawData$ === void 0 ? void 0 : _this$rawData$.name, unit: (_config$innerContent$2 = config === null || config === void 0 ? void 0 : (_config$innerContent2 = config.innerContent) === null || _config$innerContent2 === void 0 ? void 0 : _config$innerContent2.unit) !== null && _config$innerContent$2 !== void 0 ? _config$innerContent$2 : '' }, (_config$innerContent$3 = config === null || config === void 0 ? void 0 : (_config$innerContent3 = config.innerContent) === null || _config$innerContent3 === void 0 ? void 0 : _config$innerContent3.value) !== null && _config$innerContent$3 !== void 0 ? _config$innerContent$3 : this.totalData); ReactDOM.render(content, container); } }; _proto.isChangeEqual = function isChangeEqual(objValue, othValue, key) { if (key === 'selectData' && objValue !== othValue) { selectGeom(this.geom, objValue); return true; } return undefined; }; _proto.init = function init(chart, config, data) { var _ref, _config$legend$decima, _config$legend, _config$tooltip, _this2 = this, _config$tooltip2, _config$tooltip3, _config$tooltip4, _config$tooltip5; var defs = { type: { type: 'cat' } }; if (config.autoSort) { data.sort(function (a, b) { return b.y - a.y; }); } // 计算得总数据 var totalData = 0; data.forEach(function (d) { if (d.y < 0 && config.filterNegativeNumbers) { d.extra.push({ rawNumber: d.y }); d.y = 0; } totalData += d.y; }); this.totalData = numberDecimal(totalData, (_ref = (_config$legend$decima = config === null || config === void 0 ? void 0 : (_config$legend = config.legend) === null || _config$legend === void 0 ? void 0 : _config$legend.decimal) !== null && _config$legend$decima !== void 0 ? _config$legend$decima : config === null || config === void 0 ? void 0 : (_config$tooltip = config.tooltip) === null || _config$tooltip === void 0 ? void 0 : _config$tooltip.decimal) !== null && _ref !== void 0 ? _ref : 2); // 处理后的原始数据 this.sourceData = data; chart.scale(defs); chart.data(this.sourceData); // 重要:绘制饼图时,必须声明 theta 坐标系 var thetaConfig = { // radius: 1, // 设置饼图的为100% 大小,具体大小改变在 beforeInit 中diameter的值,目前为0.8 radius: Math.max(Math.min(config.outerRadius, 1), 0.01) }; if (config.cycle) { thetaConfig.innerRadius = Math.max(Math.min(config.innerRadius, 1), 0); } if (config.startAngle !== undefined) { thetaConfig.startAngle = config.startAngle; } if (config.endAngle !== undefined) { thetaConfig.endAngle = config.endAngle; } // coordinate translate 操作会导致饼图变形,暂时换一种方式实现 /*const coord = */ chart.coordinate('theta', thetaConfig); // if (config.coord) { // const { transform } = config.coord || {}; // // if (Array.isArray(transform)) { // transform.forEach((t) => { // transformCoord(coord, t); // }); // } else if (transform && typeof transform === 'object') { // transformCoord(coord, transform); // } // } // const drawPadding = getDrawPadding(config.drawPadding, config.label, this.defaultConfig.drawPadding); // 设置图例 rectLegend(this, chart, config, { // autoCollapse: false, // position: 'right', // itemTpl: (value, itemColor, checked, index) => { // const { nameFormatter, valueFormatter, showData = true } = config.legend || {}; // // const item = (this.data && this.data[index]) || {}; // const raw = (this.rawData && this.rawData[0]) || {}; // const percent = numberDecimal(item.y / this.totalData, 4); // // const result = nameFormatter ? nameFormatter(value, { // ...raw, // percent, // itemColor, // checked, // }, index) : value; // // if (showData) { // const number = valueFormatter ? valueFormatter(item.y, { // ...raw, // percent, // itemColor, // checked, // }, index) : item.y; // return `${'<li class="g2-legend-list-item item-{index} {checked}" data-color="{originColor}" data-value="{originValue}">' + // '<i class="g2-legend-marker" style="background-color:{color};"></i>' + // '<span class="g2-legend-text">'}${result}</span>` + `<span class="g2-legend-value">${number}</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:{color};"></i>' + // '<span class="g2-legend-text">'}${result}</span></li>`; // }, // 'g2-legend': { // ...legendHtmlContainer, // position: 'static', // overflow: 'auto', // // inline flex items 不能使用百分比的margin/padding,设置为固定大小 // marginLeft: `${Math.max(pxToNumber(themes['widgets-font-size-4']) - drawPadding[1], 0)}px`, // }, // 'g2-legend-list-item': { // ...legendHtmlListItem, // marginRight: 0, // }, }, 'single', null, true, function (item, index) { var name = item.name; var raw = _this2.rawData && _this2.rawData[0] || {}; var value = 0; raw.data && raw.data.forEach(function (r) { if (Array.isArray(r) && r[0] === name) { value = r[1]; } else if (typeof r === 'object' && r.x === name) { value = r.y; } }); var percent = _this2.totalData === 0 ? 0 : numberDecimal(value / _this2.totalData, 4); return _extends({}, raw, { percent: percent }, item); }); // 饼图单独处理 // 进位相关配置项 var formatConfig; // 当tooltip中配置了单位相关信息时,直接使用tooltip的配置项,否则使用y轴配置项 if (typeof (config === null || config === void 0 ? void 0 : config.tooltip) === 'object' && (config !== null && config !== void 0 && (_config$tooltip2 = config.tooltip) !== null && _config$tooltip2 !== void 0 && _config$tooltip2.valueType || config !== null && config !== void 0 && (_config$tooltip3 = config.tooltip) !== null && _config$tooltip3 !== void 0 && _config$tooltip3.unit || config !== null && config !== void 0 && (_config$tooltip4 = config.tooltip) !== null && _config$tooltip4 !== void 0 && _config$tooltip4.needUnitTransform || config !== null && config !== void 0 && (_config$tooltip5 = config.tooltip) !== null && _config$tooltip5 !== void 0 && _config$tooltip5.unitTransformTo)) { formatConfig = config.tooltip; } else { var _config$legend2; formatConfig = (_config$legend2 = config === null || config === void 0 ? void 0 : config.legend) !== null && _config$legend2 !== void 0 ? _config$legend2 : {}; } var defaultValueFormatter = customFormatter(formatConfig); // tooltip rectTooltip(this, chart, config, { showTitle: false, showMarkers: false, showCrosshairs: false, shared: false }, function (ev) { var raw = _this2.rawData && _this2.rawData[0] || {}; var items = ev.data.items; items.forEach(function (item, index) { var percent = numberDecimal(item.value / _this2.totalData, 4); if (typeof config.tooltip === 'boolean') { item.value = defaultValueFormatter(item.value); } if (typeof config.tooltip === 'object') { if (config.tooltip.valueFormatter) { item.value = config.tooltip.valueFormatter(item.value, _extends({}, raw, { percent: percent }), index, items); } else { item.value = defaultValueFormatter(item.value); } if (config.tooltip.nameFormatter) { item.name = config.tooltip.nameFormatter(item.name, _extends({}, raw, { percent: percent }), index, items); } } }); }, { showTitle: false, showMarkers: false, showCrosshairs: false, shared: false }); this.geom = chart.interval().position('y').adjust('stack'); this.geom = this.geom.color('x', config.colors); if (typeof config.animate === 'object') { this.geom.animate(config.animate); } if (config.select) { chart.interaction('element-single-selected', { start: [{ isEnable: function isEnable(context) { if (context.view.options.data.length > 1) { return true; } return false; }, trigger: 'element:click', action: 'element-single-selected:toggle' }] }); } geomStyle(this.geom, config.geomStyle); var labelField = 'y'; label({ geom: this.geom, config: config, field: labelField, componentConfig: { offset: 20, content: function (v, item, index) { if (typeof config.label === 'boolean') { return v[labelField]; } if (config.label.labelFormatter) { var percent = numberDecimal(v[labelField] / _this2.totalData, 4); return config.label.labelFormatter(v[labelField], _extends({}, item, { percent: percent }), index); } return v[labelField]; } } }); polarLegendLayout(chart); // 空数据渲染效果 chart.on('beforepaint', function () { if (_this2.totalData !== 0 && _this2.noDataShape) { _this2.noDataShape.remove(true); _this2.noDataShape = null; } }); circleAnnotation(chart, config, this.size, 'G2Pie'); // 环图中心内容 if (config.cycle && config.innerContent && !this.props.children && !this.isEmpty && !this.props.loading && !this.props.errorInfo) { var _config$innerContent$4, _config$innerContent4, _this$rawData2, _this$rawData2$, _config$innerContent$5, _config$innerContent5, _config$innerContent$6, _config$innerContent6; var container = document.createElement('div'); container.className = FullCrossName + "-children"; var firstChild = this.chartDom.firstChild; this.chartDom.insertBefore(container, firstChild); var content = /*#__PURE__*/React.createElement(Wnumber, { bottomTitle: (_config$innerContent$4 = config === null || config === void 0 ? void 0 : (_config$innerContent4 = config.innerContent) === null || _config$innerContent4 === void 0 ? void 0 : _config$innerContent4.title) !== null && _config$innerContent$4 !== void 0 ? _config$innerContent$4 : (_this$rawData2 = this.rawData) === null || _this$rawData2 === void 0 ? void 0 : (_this$rawData2$ = _this$rawData2[0]) === null || _this$rawData2$ === void 0 ? void 0 : _this$rawData2$.name, unit: (_config$innerContent$5 = config === null || config === void 0 ? void 0 : (_config$innerContent5 = config.innerContent) === null || _config$innerContent5 === void 0 ? void 0 : _config$innerContent5.unit) !== null && _config$innerContent$5 !== void 0 ? _config$innerContent$5 : '' }, (_config$innerContent$6 = config === null || config === void 0 ? void 0 : (_config$innerContent6 = config.innerContent) === null || _config$innerContent6 === void 0 ? void 0 : _config$innerContent6.value) !== null && _config$innerContent$6 !== void 0 ? _config$innerContent$6 : this.totalData); ReactDOM.render(content, container); } else if (!this.props.children) { var _this$chartDom$getEle2; // 删去中心内容 var _container = (_this$chartDom$getEle2 = this.chartDom.getElementsByClassName(FullCrossName + "-children")) === null || _this$chartDom$getEle2 === void 0 ? void 0 : _this$chartDom$getEle2[0]; if (_container) { this.chartDom.removeChild(_container); } } chart.on('afterpaint', function () { // 默认选中效果 selectGeom(_this2.geom, config.selectData); updateChildrenPosition(chart, _this2.chartDom); if (_this2.totalData === 0) { var bgGroup = chart.getLayer('bg'); var coordinate = chart.getCoordinate(); var radius = coordinate.radius, innerRadius = coordinate.innerRadius; var _coordinate$getCenter = coordinate.getCenter(), centerX = _coordinate$getCenter.x, centerY = _coordinate$getCenter.y; var pieSize = Math.min(chart.coordinateBBox.width, chart.coordinateBBox.height) * radius; var outerR = pieSize / 2; var path = [['M', centerX, centerY - outerR], ['A', outerR, outerR, 0, 1, 1, centerX, centerY + outerR], ['A', outerR, outerR, 0, 1, 1, centerX, centerY - outerR] // ['Z'], ]; if (innerRadius > 0) { var innerR = pieSize * innerRadius / 2; path.push(['M', centerX, centerY - innerR], ['A', innerR, innerR, 0, 0, 0, centerX, centerY + innerR], ['A', innerR, innerR, 0, 0, 0, centerX, centerY - innerR] // ['Z'], ); } if (!_this2.noDataShape) { _this2.noDataShape = bgGroup.addShape({ id: 'no-data-path', name: 'no-data-path', type: 'path', attrs: { path: path, fill: themes['widgets-circle-stroke-background'] } }); } else { _this2.noDataShape.attr('path', path); } // shape.set('tip', 'sdfhsjkdhk'); // // registerInteraction('no-data-text', { // start: [ // { // trigger: 'no-data-path:mousemove', // action: 'ellipsis-text:show', // throttle: { wait: 50, leading: true, trailing: false }, // }, // { // trigger: 'no-data-path:touchstart', // action: 'ellipsis-text:show', // throttle: { wait: 50, leading: true, trailing: false }, // }, // ], // end: [ // { trigger: 'no-data-path:mouseleave', action: 'ellipsis-text:hide' }, // { trigger: 'no-data-path:touchend', action: 'ellipsis-text:hide' }, // ], // }); } }); }; _proto.destroy = function destroy() { this.noDataShape = null; }; return Pie; }(Base); var Wpie = errorWrap(Pie); export default Wpie;