stackY.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.StackY = void 0;
  4. const util_1 = require("@antv/util");
  5. const helper_1 = require("./utils/helper");
  6. const order_1 = require("./utils/order");
  7. /**
  8. * The stack transform group marks into series by color channel,
  9. * and then produce new y channel for each series by specified order,
  10. * say to form vertical "stacks" by specified channels.
  11. */
  12. const StackY = (options = {}) => {
  13. const { groupBy = 'x', orderBy = null, reverse = false, y: fromY = 'y', y1: fromY1 = 'y1', series = true, } = options;
  14. return (I, mark) => {
  15. const { data, encode, style = {} } = mark;
  16. const [Y, fy] = (0, helper_1.columnOf)(encode, 'y');
  17. const [Y1, fy1] = (0, helper_1.columnOf)(encode, 'y1');
  18. const [S] = series
  19. ? (0, helper_1.maybeColumnOf)(encode, 'series', 'color')
  20. : (0, helper_1.columnOf)(encode, 'color');
  21. // Create groups and apply specified order for each group.
  22. const groups = (0, order_1.createGroups)(groupBy, I, mark);
  23. const createComparator = (0, order_1.normalizeComparator)(orderBy);
  24. const comparator = createComparator(data, Y, S);
  25. if (comparator)
  26. (0, order_1.applyOrder)(groups, comparator);
  27. // Stack y channels to produce new y and y1 channel.
  28. const newY = new Array(I.length);
  29. const newY1 = new Array(I.length);
  30. const TY = new Array(I.length);
  31. const F = [];
  32. const L = [];
  33. for (const G of groups) {
  34. if (reverse)
  35. G.reverse();
  36. // For range interval with specified y and y1.
  37. const start = Y1 ? +Y1[G[0]] : 0;
  38. // Split positive indices of Y and negative Y.
  39. const PG = [];
  40. const NG = [];
  41. for (const i of G) {
  42. const y = (TY[i] = +Y[i] - start);
  43. if (y < 0)
  44. NG.push(i);
  45. else if (y >= 0)
  46. PG.push(i);
  47. }
  48. // Store the first and last layer.
  49. const FG = PG.length > 0 ? PG : NG;
  50. const LG = NG.length > 0 ? NG : PG;
  51. let i = PG.length - 1;
  52. let j = 0;
  53. // Find the last non-zero index.
  54. while (i > 0 && Y[FG[i]] === 0)
  55. i--;
  56. // Find the first non-zero index.
  57. while (j < LG.length - 1 && Y[LG[j]] === 0)
  58. j++;
  59. F.push(FG[i]);
  60. L.push(LG[j]);
  61. // Stack negative y in reverse order.
  62. let ny = start;
  63. for (const i of NG.reverse()) {
  64. const y = TY[i];
  65. ny = newY[i] = (newY1[i] = ny) + y;
  66. }
  67. // Stack positive y in input order.
  68. let py = start;
  69. for (const i of PG) {
  70. const y = TY[i];
  71. if (y > 0)
  72. py = newY[i] = (newY1[i] = py) + y;
  73. else
  74. newY[i] = newY1[i] = py;
  75. }
  76. }
  77. // Only set top radius for the first layer,
  78. // and set bottom radius for the last layer.
  79. const FS = new Set(F);
  80. const LS = new Set(L);
  81. // Choose new y or y1 channel as the new y channel.
  82. const V = fromY === 'y' ? newY : newY1;
  83. const V1 = fromY1 === 'y' ? newY : newY1;
  84. return [
  85. I,
  86. (0, util_1.deepMix)({}, mark, {
  87. encode: {
  88. y0: (0, helper_1.inferredColumn)(Y, fy),
  89. y: (0, helper_1.column)(V, fy),
  90. y1: (0, helper_1.column)(V1, fy1),
  91. },
  92. style: Object.assign({ first: (_, i) => FS.has(i), last: (_, i) => LS.has(i) }, style),
  93. }),
  94. ];
  95. };
  96. };
  97. exports.StackY = StackY;
  98. exports.StackY.props = {};
  99. //# sourceMappingURL=stackY.js.map