text: import { __assign, __extends } from "tslib";
  import { deepMix, contains, isFunction, get, findIndex, isEqual, each, set, isArray, assign } from '@antv/util';
  import { createDom, modifyCSS } from '@antv/dom-util';
  import { HtmlTooltipTheme, TooltipCssConst, DEFAULT_ANIMATE_CFG, _ORIGIN, } from '../../dependents';
  import { registerPlotType } from '../../base/global';
  import ViewLayer from '../../base/view-layer';
  import { getGeom } from '../../geoms/factory';
  import './theme';
  import './geometry/shape/funnel-basic-rect';
  import './geometry/shape/funnel-dynamic-rect';
  import './animation/funnel-scale-in-x';
  import './animation/funnel-scale-in-y';
  import { mappingColor, rgb2arr } from '../../util/color';
  function lerp(a, b, factor) {
      return (1 - factor) * a + factor * b;
  }
  var G2_GEOM_MAP = {
      column: 'interval',
  };
  var PLOT_GEOM_MAP = {
      interval: 'funnel',
  };
  var FunnelLayer = /** @class */ (function (_super) {
      __extends(FunnelLayer, _super);
      function FunnelLayer(props) {
          var _this = _super.call(this, props) || this;
          _this.type = 'funnel';
          _this._shouldResetPercentages = true;
          _this._shouldResetLabels = true;
          _this._shouldResetCompareTexts = true;
          _this._legendsListenerAttached = false;
          _this._onLegendContainerMouseDown = function (e) {
              var props = _this.options;
              var targetName = e.target.get('name');
              if (targetName.startsWith('legend-item')) {
                  var legendItem = e.target.get('parent');
                  legendItem.set('unchecked', !legendItem.get('unchecked'));
                  _this.refreshPercentages();
                  _this.refreshLabels();
                  if (props.dynamicHeight) {
                      var data = _this._findCheckedDataByMouseDownLegendItem(legendItem);
                      _this._genCustomFieldForDynamicHeight(data);
                  }
                  if (props.compareField) {
                      var data = _this._findCheckedDataByMouseDownLegendItem(legendItem);
                      _this._updateDataForCompare(data);
                      _this.refreshCompareTexts();
                  }
              }
          };
          _this.adjustProps(_this.options);
          if (props.dynamicHeight) {
              _this._genCustomFieldForDynamicHeight(_this.getData());
          }
          if (props.compareField) {
              _this.options.data = _this._reduceDataForCompare(_this.getData());
          }
          return _this;
      }
      FunnelLayer.getDefaultOptions = function (props) {
          var cfg = {
              label: {
                  visible: true,
                  adjustColor: true,
              },
              percentage: {
                  visible: true,
                  offsetX: props.transpose ? 0 : 40,
                  offsetY: props.transpose ? 40 : 0,
                  spacing: 4,
                  line: {
                      visible: true,
                      style: {
                          lineWidth: 1,
                          stroke: 'rgba(0, 0, 0, 0.15)',
                      },
                  },
                  text: {
                      content: '转化率',
                      style: {
                          fill: 'rgba(0, 0, 0, 0.65)',
                      },
                  },
                  value: {
                      visible: true,
                      style: {
                          fill: 'black',
                      },
                      formatter: function (yValueUpper, yValueLower) { return ((100 * yValueLower) / yValueUpper).toFixed(2) + "%"; },
                  },
              },
              tooltip: {
                  visible: true,
                  shared: true,
                  showTitle: false,
                  showCrosshairs: false,
                  showMarkers: false,
              },
              animation: deepMix({}, DEFAULT_ANIMATE_CFG, {
                  appear: {
                      duration: 800,
                  },
              }),
              dynamicHeight: false,
              compareText: {
                  visible: true,
                  offsetX: -16,
                  offsetY: -16,
                  style: {
                      fill: 'black',
                  },
              },
              legend: {
                  position: 'bottom-center',
              },
              interactions: [{ type: 'tooltip' }, { type: 'legend-filter' }],
          };
          return deepMix({}, _super.getDefaultOptions.call(this), cfg);
      };
      FunnelLayer.prototype.getColorScale = function () {
          var xField = this.options.xField;
          if (xField) {
              return this.view.getScaleByField(xField);
          }
      };
      FunnelLayer.prototype.coord = function () {
          var props = this.options;
          var coordConfig = {
              type: 'rect',
              actions: props.transpose
                  ? props.dynamicHeight
                      ? [['transpose'], ['scale', 1, -1]]
                      : [['scale', 1, -1]]
                  : props.dynamicHeight
                      ? []
                      : [['transpose'], ['scale', 1, -1]],
          };
          // @ts-ignore
          this.setConfig('coordinate', coordConfig);
      };
      FunnelLayer.prototype.axis = function () {
          this.setConfig('axes', false);
      };
      FunnelLayer.prototype.adjustFunnel = function (funnel) {
          var props = this.options;
          // @ts-ignore
          funnel.shape = props.dynamicHeight ? 'funnel-dynamic-rect' : 'funnel-basic-rect';
          funnel.color = {
              fields: [props.xField],
              values: props.color && (Array.isArray(props.color) ? props.color : [props.color]),
          };
          if (isFunction(props.funnelStyle)) {
              // @ts-ignore
              funnel.style = { callback: props.funnelStyle };
          }
          else {
              // @ts-ignore
              funnel.style = { cfg: props.funnelStyle };
          }
          funnel.adjust = [
              {
                  type: props.dynamicHeight ? 'stack' : 'symmetric',
              },
          ];
      };
      FunnelLayer.prototype.tooltip = function () {
          var props = this.options;
          if (props.compareField) {
              deepMix(props.tooltip, {
                  htmlContent: function (title, items) {
                      var clss, el, color, elMarker;
                      clss = TooltipCssConst.CONTAINER_CLASS;
                      el = createDom("<div class=\"" + clss + "\"></div>");
                      modifyCSS(el, HtmlTooltipTheme[clss]);
                      var elRoot = el;
                      if (title) {
                          clss = TooltipCssConst.TITLE_CLASS;
                          el = createDom("<div class=\"" + clss + "\"></div>");
                          modifyCSS(el, HtmlTooltipTheme[clss]);
                          elRoot.appendChild(el);
                          var elTitle = el;
                          clss = TooltipCssConst.MARKER_CLASS;
                          el = createDom("<span class=\"" + clss + "\"></span>");
                          modifyCSS(el, HtmlTooltipTheme[clss]);
                          modifyCSS(el, { width: '10px', height: '10px' });
                          elTitle.appendChild(el);
                          elMarker = el;
                          el = createDom("<span>" + title + "</span>");
                          elTitle.appendChild(el);
                      }
                      if (items) {
                          clss = TooltipCssConst.LIST_CLASS;
                          el = createDom("<ul class=\"" + clss + "\"></ul>");
                          modifyCSS(el, HtmlTooltipTheme[clss]);
                          elRoot.appendChild(el);
                          var elList_1 = el;
                          items
                              .reduce(function (pairs, item) {
                              if (!color) {
                                  color = item.color;
                              }
                              var compareValues = get(item, 'point._origin.__compare__.compareValues');
                              var yValues = get(item, 'point._origin.__compare__.yValues');
                              yValues.forEach(function (yValue, i) { return pairs.push([compareValues[i], yValue]); });
                              return pairs;
                          }, [])
                              .forEach(function (_a, index) {
                              var compareValue = _a[0], yValue = _a[1];
                              clss = TooltipCssConst.LIST_ITEM_CLASS;
                              el = createDom("<li class=\"" + clss + "\" data-index=" + index + "></li>");
                              modifyCSS(el, HtmlTooltipTheme[clss]);
                              elList_1.appendChild(el);
                              var elListItem = el;
                              clss = TooltipCssConst.NAME_CLASS;
                              el = createDom("<span class=\"" + clss + "\">" + compareValue + "</span>");
                              modifyCSS(el, HtmlTooltipTheme[clss]);
                              elListItem.appendChild(el);
                              clss = TooltipCssConst.VALUE_CLASS;
                              el = createDom("<span class=\"" + clss + "\">" + yValue + "</span>");
                              modifyCSS(el, HtmlTooltipTheme[clss]);
                              elListItem.appendChild(el);
                          });
                      }
                      if (color && elMarker) {
                          modifyCSS(elMarker, { backgroundColor: color });
                      }
                      return elRoot;
                  },
              });
          }
          _super.prototype.tooltip.call(this);
      };
      FunnelLayer.prototype.addGeometry = function () {
          var props = this.options;
          var funnel = getGeom('interval', 'main', {
              positionFields: [props.dynamicHeight ? '_' : props.xField, props.yField],
              plot: this,
          });
          this.adjustFunnel(funnel);
          this.funnel = funnel;
          this.setConfig('geometry', funnel);
      };
      FunnelLayer.prototype.animation = function () {
          var _this = this;
          _super.prototype.animation.call(this);
          var props = this.options;
          if (props.animation === false) {
              /** 关闭动画 */
              this.funnel.animate = false;
          }
          else {
              var data_1 = this.getData();
              var appearDuration = get(props, 'animation.appear.duration');
              var appearDurationEach_1 = appearDuration / (data_1.length || 1);
              if (this._animationAppearTimeoutHandler) {
                  clearTimeout(this._animationAppearTimeoutHandler);
                  delete this._animationAppearTimeoutHandler;
              }
              this._animationAppearTimeoutHandler = setTimeout(function () {
                  _this.fadeInPercentages(appearDurationEach_1);
                  if (props.compareField) {
                      _this.fadeInCompareTexts(appearDurationEach_1);
                  }
                  delete _this._animationAppearTimeoutHandler;
              }, appearDuration);
              this.funnel.animate = deepMix({}, props.animation, {
                  appear: {
                      animation: props.transpose ? 'funnelScaleInX' : 'funnelScaleInY',
                      duration: appearDurationEach_1,
                      delay: function (datum) { return findIndex(data_1, function (o) { return isEqual(o, datum); }) * appearDurationEach_1; },
                      callback: function (shape) {
                          _this.fadeInLabels(shape, 0.5 * appearDurationEach_1);
                      },
                  },
                  enter: {
                      animation: 'fade-in',
                  },
              });
          }
      };
      FunnelLayer.prototype.afterRender = function () {
          var props = this.options;
          this.resetLabels();
          this.resetPercentages();
          if (props.compareField) {
              this.resetCompareTexts();
          }
          if (props.padding == 'auto') {
              var percentageContainer = this._findPercentageContainer();
              if (percentageContainer) {
                  this.paddingController.registerPadding(percentageContainer, 'inner', true);
              }
              var compareTextContainer = this._findCompareTextContainer();
              if (compareTextContainer) {
                  this.paddingController.registerPadding(compareTextContainer, 'inner', true);
              }
          }
          _super.prototype.afterRender.call(this);
          if (props.animation === false) {
              this.fadeInLabels();
              this.fadeInPercentages();
              if (props.compareField) {
                  this.fadeInCompareTexts();
              }
          }
          if (!this._legendsListenerAttached) {
              this._legendsListenerAttached = true;
              // @ts-ignore
              var legendContainer = this.view.getController('legend').container;
              legendContainer.on('mousedown', this._onLegendContainerMouseDown);
          }
      };
      FunnelLayer.prototype.updateConfig = function (cfg) {
          cfg = this.adjustProps(cfg);
          _super.prototype.updateConfig.call(this, cfg);
          this._legendsListenerAttached = false;
      };
      FunnelLayer.prototype.changeData = function (data) {
          var props = this.options;
          if (props.animation !== false) {
              this._shouldResetPercentages = false;
              this._shouldResetLabels = false;
          }
          if (props.dynamicHeight) {
              var checkedData = this._findCheckedDataInNewData(data);
              this._genCustomFieldForDynamicHeight(checkedData);
          }
          if (props.compareField) {
              data = this._reduceDataForCompare(data);
              var checkedData = this._findCheckedDataInNewData(data);
              this._updateDataForCompare(checkedData);
          }
          _super.prototype.changeData.call(this, data);
          this.refreshPercentages();
          this.refreshLabels();
          if (props.compareField) {
              this.fadeInCompareTexts();
          }
      };
      FunnelLayer.prototype.geometryParser = function (dim, type) {
          if (dim === 'g2') {
              return G2_GEOM_MAP[type];
          }
          return PLOT_GEOM_MAP[type];
      };
      FunnelLayer.prototype.adjustProps = function (props) {
          if (props.compareField) {
              props.dynamicHeight = false;
          }
          if (props.dynamicHeight) {
              set(props, "meta." + props.yField + ".nice", false);
              set(props, 'tooltip.shared', false);
          }
          return props;
      };
      FunnelLayer.prototype.resetPercentages = function () {
          var _this = this;
          if (!this._shouldResetPercentages)
              return;
          var props = this.options;
          var _a = props.percentage || {}, offsetX = _a.offsetX, offsetY = _a.offsetY, spacing = _a.spacing, _b = _a.line, percentageLine = _b === void 0 ? {} : _b, _c = _a.text, percentageText = _c === void 0 ? {} : _c, _d = _a.value, percentageValue = _d === void 0 ? {} : _d;
          var adjustTimestamp = Date.now();
          var container = this._findPercentageContainer(true);
          this._eachShape(function (shape, index, datumLower, datumUpper) {
              if (index > 0) {
                  var _a = shape.getBBox(), minX = _a.minX, maxX = _a.maxX, maxY = _a.maxY, minY = _a.minY;
                  var x1 = props.transpose ? minX : maxX;
                  var y1 = props.transpose ? (props.compareField ? maxY : minY) : minY;
                  var _b = _this._findPercentageMembersInContainerByIndex(container, index, true), line_1 = _b.line, text_1 = _b.text, value_1 = _b.value;
                  var eachProcs_1 = [
                      function (x, y, line, text, value) {
                          if (line) {
                              line.attr(deepMix({}, percentageLine.style, {
                                  x1: x,
                                  y1: y,
                                  x2: props.transpose ? x + offsetX : x - offsetX,
                                  y2: props.transpose ? y - offsetY : y + offsetY,
                                  opacity: 0,
                              }));
                              line.set('adjustTimestamp', adjustTimestamp);
                          }
                          var textWidth = 0;
                          var valueWidth = 0;
                          var textProc = function () {
                              if (text) {
                                  text.attr(deepMix({}, percentageText.style, {
                                      x: props.transpose ? x + offsetX : x - offsetX - spacing - valueWidth - spacing,
                                      y: props.transpose ? y - offsetY - spacing : y + offsetY,
                                      opacity: 0,
                                      text: percentageText.content,
                                      textAlign: props.transpose ? 'left' : 'right',
                                      textBaseline: props.transpose ? 'bottom' : 'middle',
                                  }));
                                  text.set('adjustTimestamp', adjustTimestamp);
                                  textWidth = text.getBBox().width;
                              }
                          };
                          var valueProc = function () {
                              if (value) {
                                  value.attr(deepMix({}, percentageValue.style, {
                                      x: props.transpose ? x + offsetX + textWidth + spacing : x - offsetX - spacing,
                                      y: props.transpose ? y - offsetY - spacing : y + offsetY,
                                      opacity: 0,
                                      text: isFunction(percentageValue.formatter)
                                          ? props.compareField
                                              ? percentageValue.formatter(get(datumUpper, '__compare__.yValues.0'), get(datumLower, '__compare__.yValues.0'))
                                              : percentageValue.formatter(datumUpper[props.yField], datumLower[props.yField])
                                          : '',
                                      textAlign: props.transpose ? 'left' : 'right',
                                      textBaseline: props.transpose ? 'bottom' : 'middle',
                                  }));
                                  value.set('adjustTimestamp', adjustTimestamp);
                                  valueWidth = value.getBBox().width;
                              }
                          };
                          if (props.transpose) {
                              textProc();
                              valueProc();
                          }
                          else {
                              valueProc();
                              textProc();
                          }
                      },
                      function (x, y, line, text, value) {
                          if (line) {
                              line.attr(deepMix({}, percentageLine.style, {
                                  x1: x,
                                  y1: y,
                                  x2: x + offsetX,
                                  y2: props.transpose ? (props.compareField ? y + offsetY : y - offsetY) : y + offsetY,
                                  opacity: 0,
                              }));
                              line.set('adjustTimestamp', adjustTimestamp);
                          }
                          var textWidth = 0;
                          if (text) {
                              text.attr(deepMix({}, percentageText.style, {
                                  x: props.transpose ? x + offsetX : x + offsetX + spacing,
                                  y: props.transpose
                                      ? props.compareField
                                          ? y + offsetY + spacing
                                          : y - offsetY - spacing
                                      : y + offsetY,
                                  opacity: 0,
                                  text: percentageText.content,
                                  textAlign: 'left',
                                  textBaseline: props.transpose ? (props.compareField ? 'top' : 'bottom') : 'middle',
                              }));
                              text.set('adjustTimestamp', adjustTimestamp);
                              textWidth = text.getBBox().width;
                          }
                          if (value) {
                              value.attr(deepMix({}, percentageValue.style, {
                                  x: props.transpose ? x + offsetX + textWidth + spacing : x + offsetX + spacing + textWidth + spacing,
                                  y: props.transpose
                                      ? props.compareField
                                          ? y + offsetY + spacing
                                          : y - offsetY - spacing
                                      : y + offsetY,
                                  opacity: 0,
                                  text: isFunction(percentageValue.formatter)
                                      ? props.compareField
                                          ? percentageValue.formatter(get(datumUpper, "__compare__.yValues.1"), get(datumLower, "__compare__.yValues.1"))
                                          : percentageValue.formatter(datumUpper[props.yField], datumLower[props.yField])
                                      : '',
                                  textAlign: 'left',
                                  textBaseline: props.transpose ? (props.compareField ? 'top' : 'bottom') : 'middle',
                              }));
                              value.set('adjustTimestamp', adjustTimestamp);
                          }
                      },
                  ];
                  if (props.compareField) {
                      var _c = [minX, minY], x0 = _c[0], y0 = _c[1];
                      [
                          [x0, y0],
                          [x1, y1],
                      ].forEach(function (_a, i) {
                          var x = _a[0], y = _a[1];
                          return eachProcs_1[i](x, y, line_1 && line_1[i], text_1 && text_1[i], value_1 && value_1[i]);
                      });
                  }
                  else {
                      eachProcs_1[1](x1, y1, line_1, text_1, value_1);
                  }
              }
              datumUpper = datumLower;
              index++;
          });
          container.get('children').forEach(function (child) {
              if (child.get('adjustTimestamp') != adjustTimestamp) {
                  child.attr({ opacity: 0 });
                  container.set(child.get('id'), null);
                  setTimeout(function () { return child.remove(); }, 0);
              }
          });
      };
      FunnelLayer.prototype.fadeInPercentages = function (duration, callback) {
          var _this = this;
          var props = this.options;
          var container = this._findPercentageContainer();
          var eachProc = function (i) {
              var lastBBox = { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity };
              _this._eachShape(function (shape, index) {
                  var members = _this._findPercentageMembersInContainerByIndex(container, index);
                  var currBBox = { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity };
                  var eachCalc = function (member) {
                      if (member && member.get('type') == 'text') {
                          var _a = member.getBBox(), minX = _a.minX, maxX = _a.maxX, minY = _a.minY, maxY = _a.maxY;
                          if (minX < currBBox.minX)
                              currBBox.minX = minX;
                          if (maxX > currBBox.maxX)
                              currBBox.maxX = maxX;
                          if (minY < currBBox.minY)
                              currBBox.minY = minY;
                          if (maxY > currBBox.maxY)
                              currBBox.maxY = maxY;
                      }
                  };
                  each(members, function (member) { return (isArray(member) ? eachCalc(member[i]) : eachCalc(member)); });
                  if (currBBox.minX > lastBBox.maxX ||
                      currBBox.maxX < lastBBox.minX ||
                      currBBox.minY > lastBBox.maxY ||
                      currBBox.maxY < lastBBox.minY) {
                      var eachShow_1 = function (member) {
                          if (member) {
                              var attrs = {
                                  opacity: 1,
                              };
                              duration ? member.animate(attrs, duration) : member.attr(attrs);
                          }
                      };
                      each(members, function (member) { return (isArray(member) ? eachShow_1(member[i]) : eachShow_1(member)); });
                      assign(lastBBox, currBBox);
                  }
              });
          };
          props.compareField ? [0, 1].forEach(eachProc) : eachProc();
          duration && callback && setTimeout(callback, duration);
      };
      FunnelLayer.prototype.fadeOutPercentages = function (duration, callback) {
          var _this = this;
          var container = this._findPercentageContainer();
          this._eachShape(function (shape, index) {
              var members = _this._findPercentageMembersInContainerByIndex(container, index);
              var eachProc = function (member) {
                  if (member) {
                      var attrs = {
                          opacity: 0,
                      };
                      duration ? member.animate(attrs, duration) : member.attr(attrs);
                  }
              };
              each(members, function (member) { return (isArray(member) ? member.forEach(eachProc) : eachProc(member)); });
          });
          duration && callback && setTimeout(callback, duration);
      };
      FunnelLayer.prototype.refreshPercentages = function (callback) {
          var _this = this;
          var props = this.options;
          if (props.animation !== false) {
              var _a = this._calcRefreshFadeDurations(), fadeOutDuration = _a.fadeOutDuration, fadeInDuration_1 = _a.fadeInDuration;
              this._shouldResetPercentages = false;
              this.fadeOutPercentages(fadeOutDuration, function () {
                  _this._shouldResetPercentages = true;
                  _this.resetPercentages();
                  _this.fadeInPercentages(fadeInDuration_1, callback);
              });
          }
      };
      FunnelLayer.prototype._findPercentageContainer = function (createIfNotFound) {
          if (createIfNotFound === void 0) { createIfNotFound = false; }
          var middleGroup = this.view.middleGroup;
          var percentageContainer = middleGroup.get('percentageContainer');
          if (!percentageContainer && createIfNotFound) {
              percentageContainer = middleGroup.addGroup();
              middleGroup.set('percentageContainer', percentageContainer);
          }
          return percentageContainer;
      };
      FunnelLayer.prototype._findPercentageMembersInContainerByIndex = function (container, index, createIfNotFound) {
          if (createIfNotFound === void 0) { createIfNotFound = false; }
          var props = this.options;
          var _a = props.percentage || {}, visible = _a.visible, _b = _a.line, percentageLine = _b === void 0 ? {} : _b, _c = _a.text, percentageText = _c === void 0 ? {} : _c, _d = _a.value, percentageValue = _d === void 0 ? {} : _d;
          var members = {
              line: undefined,
              text: undefined,
              value: undefined,
          };
          if (visible === false || !container) {
              return members;
          }
          if (percentageLine.visible !== false) {
              var find = function (i) {
                  var lineId = "_percentage-line-" + index + "-" + i;
                  var line = container.get(lineId);
                  if (!line && createIfNotFound) {
                      line = container.addShape({ id: lineId, type: 'line', attrs: {} });
                      container.set(lineId, line);
                  }
                  return line;
              };
              var line = props.compareField ? [0, 1].map(find) : find(0);
              members.line = line;
          }
          if (percentageText.visible !== false) {
              var find = function (i) {
                  var textId = "_percentage-text-" + index + "-" + i;
                  var text = container.get(textId);
                  if (!text && createIfNotFound) {
                      text = container.addShape({ id: textId, type: 'text', attrs: {} });
                      container.set(textId, text);
                  }
                  return text;
              };
              var text = props.compareField ? [0, 1].map(find) : find(0);
              members.text = text;
          }
          if (percentageValue.visible !== false) {
              var find = function (i) {
                  var valueId = "_percentage-value-" + index + "-" + i;
                  var value = container.get(valueId);
                  if (!value && createIfNotFound) {
                      value = container.addShape({ id: valueId, type: 'text', attrs: {} });
                      container.set(valueId, value);
                  }
                  return value;
              };
              var value = props.compareField ? [0, 1].map(find) : find(0);
              members.value = value;
          }
          return members;
      };
      FunnelLayer.prototype._calcRefreshFadeDurations = function () {
          var props = this.options;
          var updateDuration = get(props, 'animation.update.duration');
          var enterDuration = get(props, 'animation.enter.duration');
          var fadeInDuration = Math.min(enterDuration, updateDuration) * 0.6;
          var fadeOutDuration = Math.max(enterDuration, updateDuration) * 1.2;
          return { fadeInDuration: fadeInDuration, fadeOutDuration: fadeOutDuration };
      };
      FunnelLayer.prototype.resetLabels = function () {
          var _this = this;
          if (!this._shouldResetLabels)
              return;
          var props = this.options;
          var xField = props.xField, yField = props.yField;
          var adjustTimestamp = Date.now();
          var labelsContainer = this._getGeometry().labelsContainer;
          var labelProps = props.label || {};
          var labelStyle = deepMix(__assign({}, this.theme.label), props.label.style, {
              opacity: 0,
              textAlign: 'center',
              textBaseline: 'middle',
          });
          var datumTop;
          this._eachShape(function (shape, index, datum, elementIndex) {
              var _a;
              var element = shape.get('element');
              if (index == 0) {
                  datumTop = datum;
              }
              var _b = shape.getBBox(), minX = _b.minX, maxX = _b.maxX, minY = _b.minY, maxY = _b.maxY;
              var xValue = datum[xField];
              var yValue = datum[yField];
              if (labelProps.adjustColor) {
                  labelStyle.fill = _this._getAdjustedTextFillByShape(shape);
              }
              var compare = datum.__compare__;
              var content;
              var formatArgs = (_a = {},
                  _a[_ORIGIN] = datum,
                  _a.element = element,
                  _a.elementIndex = elementIndex,
                  _a.mappingDatum = [].concat(element.getModel().mappingData)[0],
                  _a.mappingDatumIndex = 0,
                  _a);
              if (labelProps.formatter) {
                  content = labelProps.formatter(xValue, formatArgs, index, yValue, datumTop[yField]);
              }
              else {
                  if (compare) {
                      content = [0, 1].map(function () { return "" + yValue; }).join(props.transpose ? '\n\n' : '    ');
                  }
                  else {
                      content = xValue + " " + yValue;
                  }
              }
              var label = _this._findLabelInContainerByIndex(labelsContainer, index, true);
              var ratio = compare ? compare.yValues[0] / (compare.yValues[0] + compare.yValues[1]) : 0.5;
              label.attr(__assign(__assign({}, labelStyle), { x: lerp(minX, maxX, !props.transpose ? ratio : 0.5), y: lerp(minY, maxY, props.transpose ? ratio : 0.5), text: content }));
              label.set('adjustTimestamp', adjustTimestamp);
          });
          labelsContainer.get('children').forEach(function (label) {
              if (label.get('adjustTimestamp') != adjustTimestamp) {
                  label.attr({ opacity: 0 });
                  labelsContainer.set(label.get('id'), null);
                  setTimeout(function () { return label.remove(); });
              }
          });
      };
      FunnelLayer.prototype.fadeInLabels = function (targetShape, duration, callback) {
          var _this = this;
          var labelsContainer = this._getGeometry().labelsContainer;
          this._eachShape(function (shape, index) {
              if (!targetShape || targetShape == shape) {
                  var label = _this._findLabelInContainerByIndex(labelsContainer, index);
                  if (label) {
                      var shapeBBox = shape.getBBox();
                      var labelBBox = label.getBBox();
                      if (labelBBox.minX >= shapeBBox.minX &&
                          labelBBox.maxX <= shapeBBox.maxX &&
                          labelBBox.minY >= shapeBBox.minY &&
                          labelBBox.maxY <= shapeBBox.maxY) {
                          var attrs = {
                              opacity: 1,
                          };
                          duration ? label.animate(attrs, duration) : label.attr(attrs);
                      }
                  }
              }
          });
          duration && callback && setTimeout(callback, duration);
      };
      FunnelLayer.prototype.fadeOutLabels = function (targetShape, duration, callback) {
          var _this = this;
          var labelsContainer = this._getGeometry().labelsContainer;
          this._eachShape(function (shape, index) {
              if (!targetShape || targetShape == shape) {
                  var label = _this._findLabelInContainerByIndex(labelsContainer, index);
                  if (label) {
                      var attrs = {
                          opacity: 0,
                      };
                      duration ? label.animate(attrs, duration) : label.attr(attrs);
                  }
              }
          });
          duration && callback && setTimeout(callback, duration);
      };
      FunnelLayer.prototype.refreshLabels = function (callback) {
          var _this = this;
          var props = this.options;
          if (props.animation !== false) {
              var _a = this._calcRefreshFadeDurations(), fadeOutDuration = _a.fadeOutDuration, fadeInDuration_2 = _a.fadeInDuration;
              this._shouldResetLabels = false;
              this.fadeOutLabels(null, fadeOutDuration, function () {
                  _this._shouldResetLabels = true;
                  _this.resetLabels();
                  _this.fadeInLabels(null, fadeInDuration_2, callback);
              });
          }
      };
      FunnelLayer.prototype._findLabelInContainerByIndex = function (container, index, createIfNotFound) {
          var _a;
          if (createIfNotFound === void 0) { createIfNotFound = false; }
          var props = this.options;
          var label;
          if (((_a = props.label) === null || _a === void 0 ? void 0 : _a.visible) === false) {
              return label;
          }
          var labelId = "_label-" + index;
          label = container.get(labelId);
          if (!label && createIfNotFound) {
              label = container.addShape({
                  id: labelId,
                  type: 'text',
                  attrs: {},
              });
              container.set(labelId, label);
          }
          return label;
      };
      FunnelLayer.prototype.resetCompareTexts = function () {
          if (!this._shouldResetCompareTexts)
              return;
          var props = this.options;
          var shapeParentBBox;
          var compare;
          this._eachShape(function (shape, index, datum) {
              if (index == 0) {
                  shapeParentBBox = shape.get('parent').getBBox();
                  compare = get(datum, '__compare__');
              }
          });
          if (shapeParentBBox && compare && get(props, 'compareText.visible') !== false) {
              var container_1 = this._findCompareTextContainer(true);
              var yValuesMax_1 = compare.yValuesMax, compareValues_1 = compare.compareValues;
              var minX_1 = shapeParentBBox.minX, maxX_1 = shapeParentBBox.maxX, minY_1 = shapeParentBBox.minY, maxY_1 = shapeParentBBox.maxY;
              var compareTexts_1 = container_1.get('children');
              [0, 1].forEach(function (i) {
                  var compareText = compareTexts_1[i];
                  if (!compareText) {
                      compareText = container_1.addShape({ type: 'text' });
                  }
                  compareText.attr(deepMix({}, get(props, 'compareText.style'), {
                      text: props.transpose ? compareValues_1[i] : i ? "  " + compareValues_1[i] : compareValues_1[i] + "  ",
                      x: props.transpose
                          ? minX_1 + get(props, 'compareText.offsetX')
                          : lerp(minX_1, maxX_1, yValuesMax_1[0] / (yValuesMax_1[0] + yValuesMax_1[1])),
                      y: props.transpose
                          ? lerp(minY_1, maxY_1, yValuesMax_1[0] / (yValuesMax_1[0] + yValuesMax_1[1])) + (i ? 8 : -8)
                          : minY_1 + get(props, 'compareText.offsetY'),
                      opacity: 0,
                      textAlign: props.transpose ? 'right' : i ? 'left' : 'right',
                      textBaseline: props.transpose ? (i ? 'top' : 'bottom') : 'bottom',
                  }));
              });
          }
      };
      FunnelLayer.prototype.fadeInCompareTexts = function (duration, callback) {
          var container = this._findCompareTextContainer();
          if (container) {
              var compareTexts_2 = container.get('children');
              [0, 1].forEach(function (i) {
                  var compareText = compareTexts_2[i];
                  if (compareText) {
                      var attrs = {
                          opacity: 1,
                      };
                      duration ? compareText.animate(attrs, duration) : compareText.attr(attrs);
                  }
              });
          }
          duration && callback && setTimeout(callback, duration);
      };
      FunnelLayer.prototype.fadeOutCompareTexts = function (duration, callback) {
          var container = this._findCompareTextContainer();
          if (container) {
              var compareTexts_3 = container.get('children');
              [0, 1].forEach(function (i) {
                  var compareText = compareTexts_3[i];
                  if (compareText) {
                      var attrs = {
                          opacity: 0,
                      };
                      duration ? compareText.animate(attrs, duration) : compareText.attr(attrs);
                  }
              });
          }
          duration && callback && setTimeout(callback, duration);
      };
      FunnelLayer.prototype.refreshCompareTexts = function (callback) {
          var _this = this;
          var props = this.options;
          if (props.animation !== false) {
              var _a = this._calcRefreshFadeDurations(), fadeInDuration_3 = _a.fadeInDuration, fadeOutDuration = _a.fadeOutDuration;
              this._shouldResetCompareTexts = false;
              this.fadeOutCompareTexts(fadeOutDuration, function () {
                  _this._shouldResetCompareTexts = true;
                  _this.resetCompareTexts();
                  _this.fadeInCompareTexts(fadeInDuration_3, callback);
              });
          }
      };
      FunnelLayer.prototype._findCompareTextContainer = function (createIfNotFound) {
          if (createIfNotFound === void 0) { createIfNotFound = false; }
          var middleGroup = this.view.middleGroup;
          var compareTextContainer = middleGroup.get('compareTextContainer');
          if (!compareTextContainer && createIfNotFound) {
              compareTextContainer = middleGroup.addGroup();
              middleGroup.set('compareTextContainer', compareTextContainer);
          }
          return compareTextContainer;
      };
      FunnelLayer.prototype._eachShape = function (fn) {
          var _a;
          var data = this._findCheckedData(this.getData());
          var dataLen = data.length;
          var index = 0;
          var datumUpper;
          (_a = this._getGeometry()) === null || _a === void 0 ? void 0 : _a.elements.forEach(function (element, elementIndex) {
              var shape = element.shape;
              var datumLower = data[index];
              if (index < dataLen) {
                  fn(shape, index, datumLower, datumUpper, elementIndex);
              }
              datumUpper = datumLower;
              index++;
          });
      };
      FunnelLayer.prototype._getGeometry = function () {
          return this.view.geometries[0];
      };
      FunnelLayer.prototype._getAdjustedTextFillByShape = function (shape) {
          var shapeColor = shape.attr('fill');
          var shapeOpacity = shape.attr('opacity') ? shape.attr('opacity') : 1;
          var rgb = rgb2arr(shapeColor);
          var gray = Math.round(rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) / shapeOpacity;
          var colorBand = [
              { from: 0, to: 85, color: 'white' },
              { from: 85, to: 170, color: '#F6F6F6' },
              { from: 170, to: 255, color: 'black' },
          ];
          var reflect = mappingColor(colorBand, gray);
          return reflect;
      };
      FunnelLayer.prototype._genCustomFieldForDynamicHeight = function (data) {
          var props = this.options;
          var total = data.reduce(function (total, datum) { return total + datum[props.yField]; }, 0);
          var ratioUpper = 1;
          data.forEach(function (datum, index) {
              var value = datum[props.yField];
              var share = value / total;
              var ratioLower = ratioUpper - share;
              datum['__custom__'] = {
                  datumIndex: index,
                  dataLength: data.length,
                  ratioUpper: ratioUpper,
                  ratioLower: ratioLower,
                  reverse: props.transpose,
              };
              ratioUpper = ratioLower;
          });
      };
      FunnelLayer.prototype._findCheckedDataByMouseDownLegendItem = function (legendItem) {
          var flags = legendItem
              .get('parent')
              .get('children')
              .map(function (legendItem) { return !legendItem.get('unchecked'); });
          var data = this.getData().filter(function (datum, index) { return flags[index]; });
          return data;
      };
      FunnelLayer.prototype._findCheckedDataInNewData = function (newData) {
          var props = this.options;
          // @ts-ignore
          var legendContainer = this.view.getController('legend').container;
          var uncheckedXValues = legendContainer
              .findAll(function (shape) { return shape.get('name') == 'legend-item'; })
              .filter(function (legendItem) { return legendItem.get('unchecked'); })
              .map(function (legendItem) { return legendItem.get('id').replace('-legend-item-', ''); });
          var checkedData = newData.filter(function (datum) { return !contains(uncheckedXValues, datum[props.xField]); });
          return checkedData;
      };
      FunnelLayer.prototype._findCheckedData = function (data) {
          var _a;
          var props = this.options;
          if ((_a = props.legend) === null || _a === void 0 ? void 0 : _a.visible) {
              // @ts-ignore
              var legendContainer = this.view.getController('legend').container;
              var checkedXValues_1 = legendContainer
                  .findAll(function (shape) { return shape.get('name') == 'legend-item'; })
                  .filter(function (legendItem) { return !legendItem.get('unchecked'); })
                  .map(function (legendItem) { return legendItem.get('id').replace('-legend-item-', ''); });
              var checkedData = data.filter(function (datum) { return contains(checkedXValues_1, datum[props.xField]); });
              return checkedData;
          }
          else {
              return this.processData(props.data);
          }
      };
      FunnelLayer.prototype._reduceDataForCompare = function (data) {
          var props = this.options;
          var compareValueFirstVisited;
          var yValuesMax = [-Infinity, -Infinity];
          data = data.reduce(function (newData, datum) {
              var _a;
              var xValue = datum[props.xField];
              var yValue = datum[props.yField];
              var compareValue = datum[props.compareField];
              if (!compareValueFirstVisited)
                  compareValueFirstVisited = compareValue;
              var newDatum = newData.find(function (newDatum) { return newDatum[props.xField] == xValue; });
              if (!newDatum) {
                  newDatum = (_a = {},
                      _a[props.xField] = xValue,
                      _a[props.yField] = 0,
                      _a['__compare__'] = {
                          compareValues: [],
                          yValues: [],
                          yValuesMax: [],
                          yValuesNext: undefined,
                          transpose: props.transpose,
                      },
                      _a);
                  newData.push(newDatum);
              }
              var idx = compareValue == compareValueFirstVisited ? 0 : 1;
              newDatum['__compare__'].yValues[idx] = yValue;
              if (yValuesMax[idx] < yValue) {
                  yValuesMax[idx] = yValue;
              }
              newDatum['__compare__'].compareValues[idx] = compareValue;
              return newData;
          }, []);
          data.forEach(function (datum, index) {
              datum[props.yField] = get(datum, '__compare__.yValues', []).reduce(function (yTotal, yValue) { return (yTotal += yValue); }, 0);
              set(datum, '__compare__.yValuesMax', yValuesMax);
              set(datum, '__compare__.yValuesNext', get(data, index + 1 + ".__compare__.yValues"));
          });
          return data;
      };
      FunnelLayer.prototype._updateDataForCompare = function (data) {
          var yValuesMax = [-Infinity, -Infinity];
          data.forEach(function (datum) {
              var yValues = get(datum, '__compare__.yValues');
              [0, 1].forEach(function (i) {
                  if (yValues[i] > yValuesMax[i]) {
                      yValuesMax[i] = yValues[i];
                  }
              });
          });
          data.forEach(function (datum, index) {
              set(datum, '__compare__.yValuesMax', yValuesMax);
              set(datum, '__compare__.yValuesNext', get(data, index + 1 + ".__compare__.yValues"));
          });
      };
      return FunnelLayer;
  }(ViewLayer));
  export default FunnelLayer;
  registerPlotType('funnel', FunnelLayer);
  //# sourceMappingURL=layer.js.map