"use strict"; var _tslib = require("tslib"); var _g6Core = require("@antv/g6-core"); var _util = require("@antv/util"); var defaultSubjectColors = _g6Core.Util.defaultSubjectColors; var FAN_NAME_PREFIX = 'fan-shape-'; /** * calculate the total value and format single value for each fan * @param donutAttrs * @param donutColorMap * @returns */ var getDonutConfig = function getDonutConfig(donutAttrs, donutColorMap) { var totalValue = 0; var configs = []; Object.keys(donutAttrs).forEach(function (name) { var value = +donutAttrs[name]; if (isNaN(value)) return; configs.push({ key: name, value: value, color: donutColorMap[name] }); totalValue += value; }); return { totalValue: totalValue, configs: configs }; }; /** * calculate the lineWidth and radius for fan shapes according to the keyShape's radius * @param keyShape * @returns */ var getDonutSize = function getDonutSize(keyShape) { var keyShapeR = keyShape.attr('r'); var innerR = 0.6 * keyShapeR; // 甜甜圈的内环半径 var arcR = (keyShapeR + innerR) / 2; // 内环半径与外环半径的平均值 var lineWidth = keyShapeR - innerR; return { lineWidth: lineWidth, arcR: arcR }; }; /** * draws one fan shape and returns the next position and angle * @param group * @param fanConfig * @returns */ var drawFan = function drawFan(group, fanConfig) { var arcR = fanConfig.arcR, arcBegin = fanConfig.arcBegin, beginAngle = fanConfig.beginAngle, config = fanConfig.config, fanIndex = fanConfig.fanIndex, lineWidth = fanConfig.lineWidth, totalValue = fanConfig.totalValue, _a = fanConfig.drawWhole, drawWhole = _a === void 0 ? false : _a, _b = fanConfig.updateShape, updateShape = _b === void 0 ? undefined : _b; var percent = config.value / totalValue; if (percent < 0.001) { // too small to add a fan return { beginAngle: beginAngle, arcBegin: arcBegin, shape: undefined, shouldEnd: false }; } var arcEnd, endAngle, isBig; // draw a path represents the whole circle, or the percentage is close to 1 if (drawWhole || percent > 0.999) { arcEnd = [arcR, 0.0001]; // [arcR * cos(2 * PI), -arcR * sin(2 * PI)] isBig = 1; } else { var angle = percent * Math.PI * 2; endAngle = beginAngle + angle; arcEnd = [arcR * Math.cos(endAngle), -arcR * Math.sin(endAngle)]; isBig = angle > Math.PI ? 1 : 0; } var style = { path: [['M', arcBegin[0], arcBegin[1]], ['A', arcR, arcR, 0, isBig, 0, arcEnd[0], arcEnd[1]]], stroke: config.color || (updateShape === null || updateShape === void 0 ? void 0 : updateShape.attr('stroke')) || defaultSubjectColors[fanIndex % defaultSubjectColors.length], lineWidth: lineWidth }; if (updateShape) { // update updateShape.attr(style); } else { // draw group['shapeMap']["".concat(FAN_NAME_PREFIX).concat(fanIndex)] = group.addShape('path', { attrs: style, name: "".concat(FAN_NAME_PREFIX).concat(fanIndex), draggable: true }); } return { beginAngle: endAngle, arcBegin: arcEnd, shape: group['shapeMap']["".concat(FAN_NAME_PREFIX).concat(fanIndex)], shouldEnd: drawWhole || percent > 0.999 }; }; /** * draws the fan shapes * @param cfg * @param group * @param keyShape * @returns */ var drawFans = function drawFans(cfg, group, keyShape) { var _a = cfg.donutAttrs, donutAttrs = _a === void 0 ? {} : _a, _b = cfg.donutColorMap, donutColorMap = _b === void 0 ? {} : _b; var attrNum = Object.keys(donutAttrs).length; if (donutAttrs && attrNum > 1) { var _c = getDonutConfig(donutAttrs, donutColorMap), configs = _c.configs, totalValue = _c.totalValue; if (totalValue) { var _d = getDonutSize(keyShape), lineWidth = _d.lineWidth, arcR = _d.arcR; var arcBegin = [arcR, 0]; var beginAngle = 0; if (attrNum === 1) { // draw a path represents a circle drawFan(group, { arcR: arcR, arcBegin: arcBegin, beginAngle: beginAngle, config: configs[0], fanIndex: 0, lineWidth: lineWidth, totalValue: totalValue, drawWhole: true }); return; } for (var i = 0; i < configs.length; i++) { var result = drawFan(group, { arcR: arcR, arcBegin: arcBegin, beginAngle: beginAngle, config: configs[i], fanIndex: i, lineWidth: lineWidth, totalValue: totalValue }); if (result.shouldEnd) return; arcBegin = result.arcBegin; beginAngle = result.beginAngle; } } } }; /** * utilizes the existing fan shapes, update them with new configs * removes the redundent fan shapes * or adds more fan shapes * @param cfg * @param item * @param keyShape */ var updateFans = function updateFans(cfg, item, keyShape) { var donutAttrs = cfg.donutAttrs, _a = cfg.donutColorMap, donutColorMap = _a === void 0 ? {} : _a; var visitMap = {}; var group = item.getContainer(); if (donutAttrs) { var _b = getDonutConfig(donutAttrs, donutColorMap), configs = _b.configs, totalValue = _b.totalValue; if (totalValue) { var _c = getDonutSize(keyShape), lineWidth = _c.lineWidth, arcR = _c.arcR; var arcBegin = [arcR, 0]; var beginAngle = 0; for (var i = 0; i < configs.length; i++) { var shapeName = "".concat(FAN_NAME_PREFIX).concat(i); var result = drawFan(group, { arcR: arcR, arcBegin: arcBegin, beginAngle: beginAngle, config: configs[i], fanIndex: i, lineWidth: lineWidth, totalValue: totalValue, drawWhole: configs.length === 1, updateShape: group['shapeMap'][shapeName] }); if (result.shape) visitMap[shapeName] = true; if (result.shouldEnd) break; arcBegin = result.arcBegin; beginAngle = result.beginAngle; } } } // remove the old shapes which are not visited, including the situation taht donutAttrs is empty var fanKeys = Object.keys(group['shapeMap']).filter(function (key) { return key.includes(FAN_NAME_PREFIX); }); fanKeys.forEach(function (key) { if (!visitMap[key]) { group['shapeMap'][key].remove(true); delete group['shapeMap'][key]; } }); }; // 饼图节点 (0, _g6Core.registerNode)('donut', { // 自定义节点时的配置 options: { size: _g6Core.BaseGlobal.defaultNode.size, style: { x: 0, y: 0, stroke: _g6Core.BaseGlobal.defaultNode.style.stroke, fill: _g6Core.BaseGlobal.defaultNode.style.fill, lineWidth: _g6Core.BaseGlobal.defaultNode.style.lineWidth }, labelCfg: { style: { fill: _g6Core.BaseGlobal.nodeLabel.style.fill, fontSize: _g6Core.BaseGlobal.nodeLabel.style.fontSize, fontFamily: _g6Core.BaseGlobal.windowFontFamily } }, // 节点上左右上下四个方向上的链接circle配置 linkPoints: { top: false, right: false, bottom: false, left: false, // circle的大小 size: _g6Core.BaseGlobal.defaultNode.linkPoints.size, lineWidth: _g6Core.BaseGlobal.defaultNode.linkPoints.lineWidth, fill: _g6Core.BaseGlobal.defaultNode.linkPoints.fill, stroke: _g6Core.BaseGlobal.defaultNode.linkPoints.stroke }, // 节点中icon配置 icon: { // 是否显示icon,值为 false 则不渲染icon show: false, // icon的地址,字符串类型 img: 'https://gw.alipayobjects.com/zos/bmw-prod/5d015065-8505-4e7a-baec-976f81e3c41d.svg', width: 20, height: 20 }, stateStyles: (0, _tslib.__assign)({}, _g6Core.BaseGlobal.nodeStateStyles) }, shapeType: 'circle', // 文本位置 labelPosition: 'center', drawShape: function drawShape(cfg, group) { var _a = (this.mergeStyle || this.getOptions(cfg)).icon, defaultIcon = _a === void 0 ? {} : _a; var style = this.getShapeStyle(cfg); var icon = (0, _util.deepMix)({}, defaultIcon, cfg.icon); var keyShape = group.addShape('circle', { attrs: style, className: "".concat(this.type, "-keyShape"), draggable: true, name: "".concat(this.type, "-keyShape") }); group['shapeMap']["".concat(this.type, "-keyShape")] = keyShape; var width = icon.width, height = icon.height, show = icon.show, text = icon.text; if (show) { if (text) { group['shapeMap']["".concat(this.type, "-icon")] = group.addShape('text', { attrs: (0, _tslib.__assign)({ x: 0, y: 0, fontSize: 12, fill: '#000', stroke: '#000', textBaseline: 'middle', textAlign: 'center' }, icon), className: "".concat(this.type, "-icon"), name: "".concat(this.type, "-icon"), draggable: true }); } else { group['shapeMap']["".concat(this.type, "-icon")] = group.addShape('image', { attrs: (0, _tslib.__assign)({ x: -width / 2, y: -height / 2 }, icon), className: "".concat(this.type, "-icon"), name: "".concat(this.type, "-icon"), draggable: true }); } } // draw the fan shapes drawFans(cfg, group, keyShape); this.drawLinkPoints(cfg, group); return keyShape; }, updateShape: function updateShape(cfg, item, keyShapeStyle, hasIcon, updateType) { // here cfg is merged configure including old model and new configs var keyShape = item.get('keyShape'); keyShape.attr((0, _tslib.__assign)({}, keyShapeStyle)); updateFans(cfg, item, keyShape); if (!undefined || (updateType === null || updateType === void 0 ? void 0 : updateType.includes('label'))) { this.updateLabel(cfg, item, updateType); } if (hasIcon) { this.updateIcon(cfg, item); } } }, 'circle');