adaptor.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. import { __assign, __rest } from "tslib";
  2. import { each, get, isArray, isEmpty, isFunction, isNil, isNumber, isString, toString } from '@antv/util';
  3. import { animation, annotation, legend, state, theme } from '../../adaptor/common';
  4. import { interval } from '../../adaptor/geometries';
  5. import { getMappingFunction } from '../../adaptor/geometries/base';
  6. import { pattern } from '../../adaptor/pattern';
  7. import { getLocale } from '../../core/locale';
  8. import { deepAssign, flow, processIllegalData, renderStatistic, template, transformLabel } from '../../utils';
  9. import { DEFAULT_OPTIONS } from './contants';
  10. import { PIE_STATISTIC } from './interactions';
  11. import { adaptOffset, getTotalValue, isAllZero } from './utils';
  12. /**
  13. * 字段
  14. * @param params
  15. */
  16. function geometry(params) {
  17. var chart = params.chart, options = params.options;
  18. var data = options.data, angleField = options.angleField, colorField = options.colorField, color = options.color, pieStyle = options.pieStyle, shape = options.shape;
  19. // 处理不合法的数据
  20. var processData = processIllegalData(data, angleField);
  21. if (isAllZero(processData, angleField)) {
  22. // 数据全 0 处理,调整 position 映射
  23. var percentageField_1 = '$$percentage$$';
  24. processData = processData.map(function (d) {
  25. var _a;
  26. return (__assign(__assign({}, d), (_a = {}, _a[percentageField_1] = 1 / processData.length, _a)));
  27. });
  28. chart.data(processData);
  29. var p = deepAssign({}, params, {
  30. options: {
  31. xField: '1',
  32. yField: percentageField_1,
  33. seriesField: colorField,
  34. isStack: true,
  35. interval: {
  36. color: color,
  37. shape: shape,
  38. style: pieStyle,
  39. },
  40. args: {
  41. zIndexReversed: true,
  42. sortZIndex: true,
  43. },
  44. },
  45. });
  46. interval(p);
  47. }
  48. else {
  49. chart.data(processData);
  50. var p = deepAssign({}, params, {
  51. options: {
  52. xField: '1',
  53. yField: angleField,
  54. seriesField: colorField,
  55. isStack: true,
  56. interval: {
  57. color: color,
  58. shape: shape,
  59. style: pieStyle,
  60. },
  61. args: {
  62. zIndexReversed: true,
  63. sortZIndex: true,
  64. },
  65. },
  66. });
  67. interval(p);
  68. }
  69. return params;
  70. }
  71. /**
  72. * meta 配置
  73. * @param params
  74. */
  75. function meta(params) {
  76. var _a;
  77. var chart = params.chart, options = params.options;
  78. var meta = options.meta, colorField = options.colorField;
  79. // meta 直接是 scale 的信息
  80. var scales = deepAssign({}, meta);
  81. chart.scale(scales, (_a = {},
  82. _a[colorField] = { type: 'cat' },
  83. _a));
  84. return params;
  85. }
  86. /**
  87. * coord 配置
  88. * @param params
  89. */
  90. function coordinate(params) {
  91. var chart = params.chart, options = params.options;
  92. var radius = options.radius, innerRadius = options.innerRadius, startAngle = options.startAngle, endAngle = options.endAngle;
  93. chart.coordinate({
  94. type: 'theta',
  95. cfg: {
  96. radius: radius,
  97. innerRadius: innerRadius,
  98. startAngle: startAngle,
  99. endAngle: endAngle,
  100. },
  101. });
  102. return params;
  103. }
  104. /**
  105. * label 配置
  106. * @param params
  107. */
  108. function label(params) {
  109. var chart = params.chart, options = params.options;
  110. var label = options.label, colorField = options.colorField, angleField = options.angleField;
  111. var geometry = chart.geometries[0];
  112. // label 为 false, 空 则不显示 label
  113. if (!label) {
  114. geometry.label(false);
  115. }
  116. else {
  117. var callback = label.callback, cfg = __rest(label, ["callback"]);
  118. var labelCfg = transformLabel(cfg);
  119. // ① 提供模板字符串的 label content 配置
  120. if (labelCfg.content) {
  121. var content_1 = labelCfg.content;
  122. labelCfg.content = function (data, dataum, index) {
  123. var name = data[colorField];
  124. var value = data[angleField];
  125. // dymatic get scale, scale is ready this time
  126. var angleScale = chart.getScaleByField(angleField);
  127. var percent = angleScale === null || angleScale === void 0 ? void 0 : angleScale.scale(value);
  128. return isFunction(content_1)
  129. ? // append percent (number) to data, users can get origin data from `dataum._origin`
  130. content_1(__assign(__assign({}, data), { percent: percent }), dataum, index)
  131. : isString(content_1)
  132. ? template(content_1, {
  133. value: value,
  134. name: name,
  135. // percentage (string), default keep 2
  136. percentage: isNumber(percent) && !isNil(value) ? "".concat((percent * 100).toFixed(2), "%") : null,
  137. })
  138. : content_1;
  139. };
  140. }
  141. var LABEL_LAYOUT_TYPE_MAP = {
  142. inner: '',
  143. outer: 'pie-outer',
  144. spider: 'pie-spider',
  145. };
  146. var labelLayoutType = labelCfg.type ? LABEL_LAYOUT_TYPE_MAP[labelCfg.type] : 'pie-outer';
  147. var labelLayoutCfg = labelCfg.layout ? (!isArray(labelCfg.layout) ? [labelCfg.layout] : labelCfg.layout) : [];
  148. labelCfg.layout = (labelLayoutType ? [{ type: labelLayoutType }] : []).concat(labelLayoutCfg);
  149. geometry.label({
  150. // fix: could not create scale, when field is undefined(attributes 中的 fields 定义都会被用来创建 scale)
  151. fields: colorField ? [angleField, colorField] : [angleField],
  152. callback: callback,
  153. cfg: __assign(__assign({}, labelCfg), { offset: adaptOffset(labelCfg.type, labelCfg.offset), type: 'pie' }),
  154. });
  155. }
  156. return params;
  157. }
  158. /**
  159. * statistic options 处理
  160. * 1. 默认继承 default options 的样式
  161. * 2. 默认使用 meta 的 formatter
  162. */
  163. export function transformStatisticOptions(options) {
  164. var innerRadius = options.innerRadius, statistic = options.statistic, angleField = options.angleField, colorField = options.colorField, meta = options.meta, locale = options.locale;
  165. var i18n = getLocale(locale);
  166. if (innerRadius && statistic) {
  167. var _a = deepAssign({}, DEFAULT_OPTIONS.statistic, statistic), titleOpt_1 = _a.title, contentOpt_1 = _a.content;
  168. if (titleOpt_1 !== false) {
  169. titleOpt_1 = deepAssign({}, {
  170. formatter: function (datum) {
  171. // 交互中, datum existed.
  172. var text = datum
  173. ? datum[colorField]
  174. : !isNil(titleOpt_1.content)
  175. ? titleOpt_1.content
  176. : i18n.get(['statistic', 'total']);
  177. var metaFormatter = get(meta, [colorField, 'formatter']) || (function (v) { return v; });
  178. return metaFormatter(text);
  179. },
  180. }, titleOpt_1);
  181. }
  182. if (contentOpt_1 !== false) {
  183. contentOpt_1 = deepAssign({}, {
  184. formatter: function (datum, data) {
  185. var dataValue = datum ? datum[angleField] : getTotalValue(data, angleField);
  186. var metaFormatter = get(meta, [angleField, 'formatter']) || (function (v) { return v; });
  187. // 交互中
  188. if (datum) {
  189. return metaFormatter(dataValue);
  190. }
  191. return !isNil(contentOpt_1.content) ? contentOpt_1.content : metaFormatter(dataValue);
  192. },
  193. }, contentOpt_1);
  194. }
  195. return deepAssign({}, { statistic: { title: titleOpt_1, content: contentOpt_1 } }, options);
  196. }
  197. return options;
  198. }
  199. /**
  200. * statistic 中心文本配置
  201. * @param params
  202. */
  203. export function pieAnnotation(params) {
  204. var chart = params.chart, options = params.options;
  205. var _a = transformStatisticOptions(options), innerRadius = _a.innerRadius, statistic = _a.statistic;
  206. // 先清空标注,再重新渲染
  207. chart.getController('annotation').clear(true);
  208. // 先进行其他 annotations,再去渲染统计文本
  209. flow(annotation())(params);
  210. /** 中心文本 指标卡 */
  211. if (innerRadius && statistic) {
  212. renderStatistic(chart, { statistic: statistic, plotType: 'pie' });
  213. }
  214. return params;
  215. }
  216. /**
  217. * 饼图 tooltip 配置
  218. * 1. 强制 tooltip.shared 为 false
  219. * @param params
  220. */
  221. function tooltip(params) {
  222. var chart = params.chart, options = params.options;
  223. var tooltip = options.tooltip, colorField = options.colorField, angleField = options.angleField, data = options.data;
  224. if (tooltip === false) {
  225. chart.tooltip(tooltip);
  226. }
  227. else {
  228. chart.tooltip(deepAssign({}, tooltip, { shared: false }));
  229. // 主要解决 all zero, 对于非 all zero 不再适用
  230. if (isAllZero(data, angleField)) {
  231. var fields = get(tooltip, 'fields');
  232. var formatter = get(tooltip, 'formatter');
  233. if (isEmpty(get(tooltip, 'fields'))) {
  234. fields = [colorField, angleField];
  235. formatter = formatter || (function (datum) { return ({ name: datum[colorField], value: toString(datum[angleField]) }); });
  236. }
  237. chart.geometries[0].tooltip(fields.join('*'), getMappingFunction(fields, formatter));
  238. }
  239. }
  240. return params;
  241. }
  242. /**
  243. * Interaction 配置 (饼图特殊的 interaction, 中心文本变更的时候,需要将一些配置参数传进去)
  244. * @param params
  245. */
  246. export function interaction(params) {
  247. var chart = params.chart, options = params.options;
  248. var _a = transformStatisticOptions(options), interactions = _a.interactions, statistic = _a.statistic, annotations = _a.annotations;
  249. each(interactions, function (i) {
  250. var _a, _b;
  251. if (i.enable === false) {
  252. chart.removeInteraction(i.type);
  253. }
  254. else if (i.type === 'pie-statistic-active') {
  255. // 只针对 start 阶段的配置,进行添加参数信息
  256. var startStages_1 = [];
  257. if (!((_a = i.cfg) === null || _a === void 0 ? void 0 : _a.start)) {
  258. startStages_1 = [
  259. {
  260. trigger: 'element:mouseenter',
  261. action: "".concat(PIE_STATISTIC, ":change"),
  262. arg: { statistic: statistic, annotations: annotations },
  263. },
  264. ];
  265. }
  266. each((_b = i.cfg) === null || _b === void 0 ? void 0 : _b.start, function (stage) {
  267. startStages_1.push(__assign(__assign({}, stage), { arg: { statistic: statistic, annotations: annotations } }));
  268. });
  269. chart.interaction(i.type, deepAssign({}, i.cfg, { start: startStages_1 }));
  270. }
  271. else {
  272. chart.interaction(i.type, i.cfg || {});
  273. }
  274. });
  275. return params;
  276. }
  277. /**
  278. * 饼图适配器
  279. * @param chart
  280. * @param options
  281. */
  282. export function adaptor(params) {
  283. // flow 的方式处理所有的配置到 G2 API
  284. return flow(pattern('pieStyle'), geometry, meta, theme, coordinate, legend, tooltip, label, state,
  285. /** 指标卡中心文本 放在下层 */
  286. pieAnnotation, interaction, animation)(params);
  287. }
  288. //# sourceMappingURL=adaptor.js.map