UNPKG

@visactor/vchart

Version:

charts lib based @visactor/VGrammar

557 lines (527 loc) 32.4 kB
import { SeriesTypeEnum } from "../interface/type"; import { BaseSeries } from "../base/base-series"; import { AttributeLevel } from "../../constant/attribute"; import { DEFAULT_DATA_KEY } from "../../constant/data"; import { PREFIX } from "../../constant/base"; import { registerDataSetInstanceTransform } from "../../data/register"; import { DataView } from "@visactor/vdataset"; import { funnel, funnelTransform } from "../../data/transforms/funnel"; import { FUNNEL_CURRENT_VALUE, FUNNEL_HEIGHT_RATIO, FUNNEL_LABEL_LINE_LENGTH, FUNNEL_LABEL_SPACE_WIDTH, FUNNEL_LAST_VALUE, FUNNEL_LAST_VALUE_RATIO, FUNNEL_MAX_SIZE, FUNNEL_MIN_SIZE, FUNNEL_NEXT_VALUE, FUNNEL_NEXT_VALUE_RATIO, FUNNEL_REACH_RATIO, FUNNEL_TRANSFORM_LEVEL, FUNNEL_TRANSFORM_RATIO, FUNNEL_VALUE_RATIO } from "../../constant/funnel"; import { calcLayoutNumber } from "../../util/space"; import { field } from "../../util/object"; import { FunnelSeriesTooltipHelper } from "./tooltip-helper"; import { isFunction, isValid, isNumber } from "@visactor/vutils"; import { FadeInOutAnimation, registerCartesianGroupClipAnimation, registerFadeInOutAnimation } from "../../animation/config"; import { animationConfig, shouldMarkDoMorph, userAnimationConfig } from "../../animation/utils"; import { registerPolygonMark } from "../../mark/polygon/polygon"; import { registerTextMark } from "../../mark/text"; import { registerRuleMark } from "../../mark/rule"; import { funnelSeriesMark } from "./constant"; import { Factory } from "../../core/factory"; import { FunnelSeriesSpecTransformer } from "./funnel-transformer"; import { CompilableData } from "../../compile/data"; import { moveAfterInArray } from "../../util/array"; import { funnel as funnelTheme } from "../../theme/builtin/common/series/funnel"; export class FunnelSeries extends BaseSeries { constructor() { super(...arguments), this.type = SeriesTypeEnum.funnel, this._funnelMarkName = "funnel", this._funnelMarkType = "polygon", this._transformMarkName = "transform", this._transformMarkType = "polygon", this.transformerConstructor = FunnelSeriesSpecTransformer, this._funnelMark = null, this._funnelTransformMark = null, this._labelMark = null, this._transformLabelMark = null, this._funnelOuterLabelMark = {}; } getCategoryField() { return this._categoryField; } setCategoryField(f) { return this._categoryField = f, this._categoryField; } getValueField() { return this._valueField; } setValueField(f) { return this._valueField = f, this._valueField; } setAttrFromSpec() { var _a, _b, _c, _d, _e; super.setAttrFromSpec(), this.setCategoryField(this._spec.categoryField), this.setValueField(this._spec.valueField), this._funnelOrient = null !== (_a = this._spec.funnelOrient) && void 0 !== _a ? _a : "top", this._shape = null !== (_b = this._spec.shape) && void 0 !== _b ? _b : "trapezoid", this._minLabelLineWidth = null !== (_e = null === (_d = null === (_c = this._spec.outerLabel) || void 0 === _c ? void 0 : _c.line) || void 0 === _d ? void 0 : _d.minLength) && void 0 !== _e ? _e : FUNNEL_LABEL_LINE_LENGTH, this._isHorizontal() ? this._funnelAlign = [ "top", "bottom" ].includes(this._spec.funnelAlign) ? this._spec.funnelAlign : "center" : this._funnelAlign = [ "left", "right" ].includes(this._spec.funnelAlign) ? this._spec.funnelAlign : "center", !this._seriesField && this._spec.categoryField && this.setSeriesField(this._spec.categoryField); } initData() { if (super.initData(), !this._data) return; registerDataSetInstanceTransform(this._dataSet, "funnel", funnel), registerDataSetInstanceTransform(this._dataSet, "funnelTransform", funnelTransform); const viewDataTransform = new DataView(this._dataSet, { name: `${PREFIX}_series_${this.id}_viewDataTransform` }); viewDataTransform.parse([ this.getViewData() ], { type: "dataview" }), this._viewDataTransform = new CompilableData(this._option, viewDataTransform); } compile() { var _a, _b; super.compile(), this._funnelOuterLabelMark && (null === (_a = this._funnelOuterLabelMark.label) || void 0 === _a || _a.compile({ group: this._rootMark.getProduct() }), null === (_b = this._funnelOuterLabelMark.line) || void 0 === _b || _b.compile({ group: this._rootMark.getProduct() })); } compileData() { var _a; super.compileData(), null === (_a = this._viewDataTransform) || void 0 === _a || _a.compile(); } getStatisticFields() { const fields = []; return fields.push({ key: this._categoryField, operations: [ "values" ] }), fields.push({ key: this._valueField, operations: [ "max", "min" ] }), fields; } _statisticViewData() { var _a, _b, _c, _d, _e, _f, _g, _h, _j; super._statisticViewData(), this._data.getDataView().transform({ type: "funnel", options: { valueField: this.getValueField(), isCone: this._spec.isCone, asCurrentValue: FUNNEL_CURRENT_VALUE, asTransformRatio: FUNNEL_TRANSFORM_RATIO, asReachRatio: FUNNEL_REACH_RATIO, asHeightRatio: FUNNEL_HEIGHT_RATIO, asValueRatio: FUNNEL_VALUE_RATIO, asNextValueRatio: FUNNEL_NEXT_VALUE_RATIO, asLastValueRatio: FUNNEL_LAST_VALUE_RATIO, asLastValue: FUNNEL_LAST_VALUE, asNextValue: FUNNEL_NEXT_VALUE, range: { min: null !== (_b = null === (_a = this._spec.range) || void 0 === _a ? void 0 : _a.min) && void 0 !== _b ? _b : null === (_d = null === (_c = this.getViewDataStatistics().latestData) || void 0 === _c ? void 0 : _c[this.getValueField()]) || void 0 === _d ? void 0 : _d.min, max: null !== (_f = null === (_e = this._spec.range) || void 0 === _e ? void 0 : _e.max) && void 0 !== _f ? _f : null === (_h = null === (_g = this.getViewDataStatistics().latestData) || void 0 === _g ? void 0 : _g[this.getValueField()]) || void 0 === _h ? void 0 : _h.max } } }), null === (_j = this._viewDataTransform.getDataView()) || void 0 === _j || _j.transform({ type: "funnelTransform", options: { asIsTransformLevel: FUNNEL_TRANSFORM_LEVEL } }); } initMark() { var _a, _b, _c, _d, _e, _f, _g, _h; if (this._funnelMark = this._createMark(Object.assign(Object.assign({}, FunnelSeries.mark.funnel), { name: this._funnelMarkName, type: this._funnelMarkType }), { themeSpec: null === (_a = this._theme) || void 0 === _a ? void 0 : _a.funnel, groupKey: this._seriesField, isSeriesMark: !0, noSeparateStyle: !0 }, { morph: shouldMarkDoMorph(this._spec, this._funnelMarkName), morphElementKey: this._seriesField }), this._spec.isTransform && (this._funnelTransformMark = this._createMark(Object.assign(Object.assign({}, FunnelSeries.mark.transform), { name: this._transformMarkName, type: this._transformMarkType }), { themeSpec: null === (_b = this._theme) || void 0 === _b ? void 0 : _b.transform, skipBeforeLayouted: !0, noSeparateStyle: !0 }), this._funnelTransformMark && this._funnelTransformMark.setData(this._viewDataTransform)), null === (_d = null === (_c = this._spec) || void 0 === _c ? void 0 : _c.outerLabel) || void 0 === _d ? void 0 : _d.visible) { const {line: line} = null !== (_e = this._spec.outerLabel) && void 0 !== _e ? _e : {}, {line: lineTheme} = null !== (_g = null === (_f = this._theme) || void 0 === _f ? void 0 : _f.outerLabel) && void 0 !== _g ? _g : {}; this._funnelOuterLabelMark.label = this._createMark(FunnelSeries.mark.outerLabel, { themeSpec: null === (_h = this._theme) || void 0 === _h ? void 0 : _h.outerLabel, markSpec: this._spec.outerLabel, skipBeforeLayouted: !0, noSeparateStyle: !0, parent: !1 }), this._funnelOuterLabelMark.line = this._createMark(FunnelSeries.mark.outerLabelLine, { themeSpec: lineTheme, markSpec: line, noSeparateStyle: !0, parent: !1 }); } } initTooltip() { this._tooltipHelper = new FunnelSeriesTooltipHelper(this), this._funnelMark && this._tooltipHelper.activeTriggerSet.mark.add(this._funnelMark), this._funnelTransformMark && this._tooltipHelper.activeTriggerSet.mark.add(this._funnelTransformMark); } getDimensionField() { return this._seriesField ? [ this._seriesField ] : []; } getMeasureField() { return [ this._valueField ]; } getGroupFields() { return null; } initMarkStyle() { var _a, _b, _c, _d; const funnelMark = this._funnelMark; funnelMark && this.setMarkStyle(funnelMark, { points: datum => this.getPoints(datum), visible: datum => isValid(datum[this._valueField]), fill: this.getColorAttribute() }, "normal", AttributeLevel.Series); const funnelTransformMark = this._funnelTransformMark; funnelTransformMark && this.setMarkStyle(funnelTransformMark, { points: datum => this.getPoints(datum) }, "normal", AttributeLevel.Series); const outerLabelMark = this._funnelOuterLabelMark.label; outerLabelMark && (this.setMarkStyle(outerLabelMark, { text: datum => `${datum[this.getCategoryField()]}`, x: datum => this._computeOuterLabelPosition(datum).x, y: datum => this._computeOuterLabelPosition(datum).y, textAlign: datum => this._computeOuterLabelPosition(datum).align, textBaseline: datum => this._computeOuterLabelPosition(datum).textBaseline, maxLineWidth: datum => this._computeOuterLabelLimit(datum), width: 0, height: 0 }, "normal", AttributeLevel.Series), isFunction(this._spec.outerLabel.formatMethod) && this.setMarkStyle(outerLabelMark, { text: datum => this._spec.outerLabel.formatMethod(`${datum[this.getCategoryField()]}`, datum) }, "normal", AttributeLevel.User_Mark)); const outerLabelLineMark = this._funnelOuterLabelMark.line; if (outerLabelLineMark && outerLabelMark) { this.setMarkStyle(outerLabelLineMark, { x: datum => this._computeOuterLabelLinePosition(datum).x1, y: datum => this._computeOuterLabelLinePosition(datum).y1, x1: datum => this._computeOuterLabelLinePosition(datum).x2, y1: datum => this._computeOuterLabelLinePosition(datum).y2 }, "normal", AttributeLevel.Series); const visible = null !== (_c = null === (_b = null === (_a = this._spec.outerLabel) || void 0 === _a ? void 0 : _a.line) || void 0 === _b ? void 0 : _b.visible) && void 0 !== _c ? _c : null === (_d = this._spec.outerLabel) || void 0 === _d ? void 0 : _d.visible; isValid(visible) && outerLabelLineMark.setVisible(visible); } } initLabelMarkStyle(labelMark) { var _a; if (!labelMark) return; const target = labelMark.getTarget(), component = labelMark.getComponent(); if (target === this._funnelMark) { this._labelMark = labelMark, this.setMarkStyle(labelMark, { text: datum => `${datum[this.getCategoryField()]} ${datum[this.getValueField()]}`, x: datum => this._computeLabelPosition(datum).x, y: datum => this._computeLabelPosition(datum).y, maxLineWidth: datum => this._computeLabelLimit(datum, this._spec.label), stroke: this.getColorAttribute() }, "normal", AttributeLevel.Series); const rootMarks = this.getCompiler().getRootMarks(); this._funnelOuterLabelMark.label && moveAfterInArray(rootMarks, this._funnelOuterLabelMark.label, component), this._funnelOuterLabelMark.line && moveAfterInArray(rootMarks, this._funnelOuterLabelMark.line, null !== (_a = this._funnelOuterLabelMark.label) && void 0 !== _a ? _a : component); } else this._funnelTransformMark && target === this._funnelTransformMark && (this._transformLabelMark = labelMark, this.setMarkStyle(labelMark, { text: datum => `${(100 * field(FUNNEL_REACH_RATIO).bind(this)(datum)).toFixed(1)}%`, x: datum => this._computeLabelPosition(datum).x, y: datum => this._computeLabelPosition(datum).y, maxLineWidth: datum => this._computeLabelLimit(datum, this._spec.transformLabel) }, "normal", AttributeLevel.Series)); } initAnimation() { var _a, _b, _c, _d, _e, _f, _g; const appearPreset = null !== (_c = null === (_b = null === (_a = this._spec) || void 0 === _a ? void 0 : _a.animationAppear) || void 0 === _b ? void 0 : _b.preset) && void 0 !== _c ? _c : "clipIn"; "clipIn" === appearPreset && this._rootMark && this._rootMark.setAnimationConfig(animationConfig(null === (_d = Factory.getAnimationInKey("cartesianGroupClip")) || void 0 === _d ? void 0 : _d({ direction: () => this._isHorizontal() ? "x" : "y", width: () => { const rootMark = this.getRootMark().getProduct(); if (rootMark) { const {x1: x1, x2: x2} = rootMark.AABBBounds; return Math.max(x1, x2); } return this.getLayoutRect().width; }, height: () => { const rootMark = this.getRootMark().getProduct(); if (rootMark) { const {y1: y1, y2: y2} = rootMark.AABBBounds; return Math.max(y1, y2); } return this.getLayoutRect().height; }, orient: () => this._isReverse() ? "negative" : "positive" }, appearPreset), userAnimationConfig("group", this._spec, this._markAttributeContext))), [ null === (_e = this._funnelOuterLabelMark) || void 0 === _e ? void 0 : _e.label ].forEach((m => { m && m.setAnimationConfig(animationConfig(Factory.getAnimationInKey("fadeInOut")(), userAnimationConfig(m.name, this._spec, this._markAttributeContext))); })), [ this._funnelMark, this._funnelTransformMark ].forEach((m => { m && m.setAnimationConfig(animationConfig(Factory.getAnimationInKey("funnel")({}, appearPreset), userAnimationConfig(m.name, this._spec, this._markAttributeContext))); })), (null === (_f = this._funnelOuterLabelMark) || void 0 === _f ? void 0 : _f.line) && this._funnelOuterLabelMark.line.setAnimationConfig(animationConfig(null === (_g = Factory.getAnimationInKey("fadeInOut")) || void 0 === _g ? void 0 : _g(), userAnimationConfig("outerLabelLine", this._spec, this._markAttributeContext))); } initGroups() {} getStackGroupFields() { return []; } getStackValueField() { return null; } initEvent() { var _a; super.initEvent(), null === (_a = this._viewDataTransform.getDataView()) || void 0 === _a || _a.target.addListener("change", (d => { this._viewDataTransform.updateData(); })); } getPoints(datum) { const isTransformLevel = this.isTransformLevel(datum), heightHalf = this._getMainAxisLength(isTransformLevel) / 2; let upperLeft, lowerLeft; isTransformLevel ? (upperLeft = "rect" === this._shape ? this._getSecondaryAxisLength(datum[FUNNEL_LAST_VALUE_RATIO]) / 2 : this._getSecondaryAxisLength(datum[FUNNEL_VALUE_RATIO]) / 2, lowerLeft = this._getSecondaryAxisLength(datum[FUNNEL_VALUE_RATIO]) / 2) : (upperLeft = this._getSecondaryAxisLength(datum[FUNNEL_VALUE_RATIO]) / 2, lowerLeft = "rect" === this._shape ? upperLeft : this._getSecondaryAxisLength(datum[FUNNEL_NEXT_VALUE_RATIO]) / 2); const {x: x, y: y} = this._getPositionByData(datum), points = this._getPolygonPoints([ x, y ], upperLeft, lowerLeft, upperLeft, lowerLeft, heightHalf); return "center" !== this._funnelAlign && this._adjustPoints(points), points; } isTransformLevel(datum) { return !!(null == datum ? void 0 : datum[FUNNEL_TRANSFORM_LEVEL]); } _buildMarkAttributeContext() { super._buildMarkAttributeContext(), this._markAttributeContext.valueToPosition = this.valueToPosition.bind(this), this._markAttributeContext.getPoints = this.getPoints.bind(this), this._markAttributeContext.isTransformLevel = this.isTransformLevel.bind(this); } valueToPosition(category) { var _a, _b, _c; const innerDatum = null === (_c = null === (_b = null === (_a = this.getViewData()) || void 0 === _a ? void 0 : _a.latestData) || void 0 === _b ? void 0 : _b.find) || void 0 === _c ? void 0 : _c.call(_b, (d => d[this._categoryField] === category)); return isValid(innerDatum) ? this._getPolygonCenter(this.getPoints(innerDatum)) : null; } dataToPosition(datum, checkInViewData) { return checkInViewData && !this.isDatumInViewData(datum) ? null : this.valueToPosition(datum[this._categoryField]); } dataToPositionX(datum) { var _a; return null === (_a = this.dataToPosition(datum)) || void 0 === _a ? void 0 : _a.x; } dataToPositionY(datum) { var _a; return null === (_a = this.dataToPosition(datum)) || void 0 === _a ? void 0 : _a.y; } dataToPositionZ(datum) { return 0; } _getMainAxisLength(isTransform = !1) { var _a; const funnelCount = this.getViewData().latestData.length, viewHeight = this._isHorizontal() ? this.getLayoutRect().width : this.getLayoutRect().height, hasTransform = !!this._spec.isTransform, gap = hasTransform ? 0 : null !== (_a = this._spec.gap) && void 0 !== _a ? _a : 0, transformCount = hasTransform ? Math.max(0, funnelCount - 1) : 0, heightRatio = this._spec.heightRatio || .5, funnelHeight = (viewHeight - gap * Math.max(0, funnelCount - 1)) / (funnelCount + heightRatio * transformCount); return isTransform ? hasTransform ? funnelHeight * heightRatio : 0 : funnelHeight; } _getSecondaryAxisLength(ratio) { const validRatio = Number.isNaN(ratio) || !Number.isFinite(ratio) ? 0 : ratio, maxSize = this._computeMaxSize(), minSize = this._computeMinSize(); return minSize + (maxSize - minSize) * validRatio; } _getPositionByData(datum) { var _a; const index = null === (_a = this.getViewData().latestData) || void 0 === _a ? void 0 : _a.findIndex((d => d[this._categoryField] === datum[this._categoryField] && d[DEFAULT_DATA_KEY] === datum[DEFAULT_DATA_KEY])); if (!isValid(index) || index < 0) return {}; const isTransform = this.isTransformLevel(datum), isHorizontal = this._isHorizontal(), viewWidth = isHorizontal ? this.getLayoutRect().height : this.getLayoutRect().width, viewHeight = isHorizontal ? this.getLayoutRect().width : this.getLayoutRect().height, centerX = viewWidth / 2; let centerY = 0; const funnelHeight = this._getMainAxisLength(), transformHeight = this._getMainAxisLength(!0); return centerY += index * (funnelHeight + transformHeight), centerY += isTransform ? -transformHeight / 2 : funnelHeight / 2, !this._spec.isTransform && this._spec.gap && (centerY += this._spec.gap * index), this._isReverse() && (centerY = viewHeight - centerY), this._isHorizontal() ? { x: centerY, y: centerX } : { x: centerX, y: centerY }; } _getPolygonPoints(center, upperLeft, lowerLeft, upperRight, lowerRight, heightHalf) { const x = center[0], y = center[1]; switch (this._funnelOrient) { case "left": return [ { x: x - heightHalf, y: y + upperLeft }, { x: x - heightHalf, y: y - upperRight }, { x: x + heightHalf, y: y - lowerRight }, { x: x + heightHalf, y: y + lowerLeft } ]; case "right": return [ { x: x + heightHalf, y: y - upperRight }, { x: x + heightHalf, y: y + upperRight }, { x: x - heightHalf, y: y + lowerLeft }, { x: x - heightHalf, y: y - lowerLeft } ]; case "bottom": return [ { x: x + upperLeft, y: y + heightHalf }, { x: x - upperRight, y: y + heightHalf }, { x: x - lowerRight, y: y - heightHalf }, { x: x + lowerLeft, y: y - heightHalf } ]; default: return [ { x: x - upperLeft, y: y - heightHalf }, { x: x + upperRight, y: y - heightHalf }, { x: x + lowerRight, y: y + heightHalf }, { x: x - lowerLeft, y: y + heightHalf } ]; } } _getPolygonCenter(points) { if (this._isHorizontal()) { const p0_x = (points[0].x + points[3].x) / 2, p0_y = (points[0].y + points[3].y) / 2; return { x: (p0_x + (points[1].x + points[2].x) / 2) / 2, y: (p0_y + (points[1].y + points[2].y) / 2) / 2 }; } const p0_x = (points[0].x + points[3].x) / 2, p0_y = (points[0].y + points[3].y) / 2; return { x: (p0_x + (points[1].x + points[2].x) / 2) / 2, y: (p0_y + (points[1].y + points[2].y) / 2) / 2 }; } _adjustPoints(points) { let upperOffset, lowerOffset, dirKey; return this._isHorizontal() ? (dirKey = "y", "left" === this._funnelOrient ? (upperOffset = "bottom" === this._funnelAlign ? -points[1].y : points[1].y, lowerOffset = "bottom" === this._funnelAlign ? -points[2].y : points[2].y) : (upperOffset = "bottom" === this._funnelAlign ? -points[0].y : points[0].y, lowerOffset = "bottom" === this._funnelAlign ? -points[3].y : points[3].y)) : (dirKey = "x", "top" === this._funnelOrient ? (upperOffset = "left" === this._funnelAlign ? points[0].x : -points[0].x, lowerOffset = "left" === this._funnelAlign ? points[3].x : -points[3].x) : (upperOffset = "left" === this._funnelAlign ? points[1].x : -points[1].x, lowerOffset = "left" === this._funnelAlign ? points[2].x : -points[2].x)), points[0][dirKey] -= upperOffset, points[1][dirKey] -= upperOffset, points[2][dirKey] -= lowerOffset, points[3][dirKey] -= lowerOffset, points; } _computeLabelPosition(datum) { const points = this.getPoints(datum); return this._getPolygonCenter(points); } _computeLabelLimit(datum, labelSpec) { const limit = null == labelSpec ? void 0 : labelSpec.limit; if (isNumber(limit)) return limit; const points = this.getPoints(datum); return "shapeSize" === limit ? this._isHorizontal() ? Math.abs(points[3].x - points[0].x) : (Math.abs(points[0].x - points[1].x) + Math.abs(points[2].x - points[3].x)) / 2 : this._isHorizontal() ? Math.abs(points[3].x - points[0].x) : void 0; } _computeOuterLabelPosition(datum) { var _a, _b; let x, y, position = null === (_a = this._spec.outerLabel) || void 0 === _a ? void 0 : _a.position, textAlign = "center", textBaseline = "middle"; if (position = this._isHorizontal() ? [ "top", "bottom" ].includes(position) ? position : "bottom" === this._funnelAlign ? "top" : "bottom" : [ "left", "right" ].includes(position) ? position : "left" === this._funnelAlign ? "right" : "left", !1 !== (null === (_b = this._spec.outerLabel) || void 0 === _b ? void 0 : _b.alignLabel)) ({x: x, y: y} = this._getPositionByData(datum)), "left" === position ? (x = 0, textAlign = "left") : "right" === position ? (x = this.getLayoutRect().width, textAlign = "right") : "top" === position ? (y = 0, textBaseline = "top") : "bottom" === position && (y = this.getLayoutRect().height, textBaseline = "bottom"); else { const {x2: x2, y2: y2} = this._computeOuterLabelLinePosition(datum); x = x2, y = y2, "left" === position ? (x -= FUNNEL_LABEL_SPACE_WIDTH, textAlign = "right") : "right" === position ? (x += FUNNEL_LABEL_SPACE_WIDTH, textAlign = "left") : "top" === position ? (y -= FUNNEL_LABEL_SPACE_WIDTH, textBaseline = "bottom") : "bottom" === position && (y += FUNNEL_LABEL_SPACE_WIDTH, textBaseline = "top"); } return { x: x, y: y, align: textAlign, textBaseline: textBaseline }; } _computeOuterLabelLimit(datum) { var _a, _b, _c, _d, _e, _f; if (this._isHorizontal()) return this._getMainAxisLength(this.isTransformLevel(datum)); const points = this.getPoints(datum), shapeMiddleWidth = (Math.abs(points[0].x - points[1].x) + Math.abs(points[2].x - points[3].x)) / 2, categoryField = this.getCategoryField(), funnelLabelBounds = null === (_d = null === (_c = null === (_b = null === (_a = this._labelMark) || void 0 === _a ? void 0 : _a.getComponent()) || void 0 === _b ? void 0 : _b.getComponent()) || void 0 === _c ? void 0 : _c.find((({attribute: attribute, type: type}) => { var _a; return "text" === type && (null === (_a = attribute.data) || void 0 === _a ? void 0 : _a[categoryField]) === datum[categoryField]; }), !0)) || void 0 === _d ? void 0 : _d.AABBBounds, funnelLabelWidth = funnelLabelBounds ? funnelLabelBounds.x2 - funnelLabelBounds.x1 : 0, outerLineSpace = this._funnelOuterLabelMark.line ? this._minLabelLineWidth : 0; let space = this.getLayoutRect().width - Math.max(shapeMiddleWidth, funnelLabelWidth); return "center" === this._funnelAlign && (space /= 2), space - outerLineSpace - (null !== (_f = null === (_e = this._spec.outerLabel) || void 0 === _e ? void 0 : _e.spaceWidth) && void 0 !== _f ? _f : FUNNEL_LABEL_SPACE_WIDTH); } _computeOuterLabelLinePosition(datum) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; const categoryField = this.getCategoryField(), outerLabelMarkBounds = null === (_d = null === (_c = null === (_b = null === (_a = this._funnelOuterLabelMark) || void 0 === _a ? void 0 : _a.label) || void 0 === _b ? void 0 : _b.getGraphics()) || void 0 === _c ? void 0 : _c.find((g => { var _a; return (null === (_a = g.context.data[0]) || void 0 === _a ? void 0 : _a[categoryField]) === datum[categoryField]; }))) || void 0 === _d ? void 0 : _d.AABBBounds, labelComponent = null === (_f = null === (_e = this._labelMark) || void 0 === _e ? void 0 : _e.getComponent()) || void 0 === _f ? void 0 : _f.getComponent(), labelMarkBounds = null === (_g = null == labelComponent ? void 0 : labelComponent.find((({attribute: attribute, type: type}) => { var _a; return "text" === type && (null === (_a = attribute.data) || void 0 === _a ? void 0 : _a[categoryField]) === datum[categoryField]; }), !0)) || void 0 === _g ? void 0 : _g.AABBBounds, outerLabelSpec = null !== (_h = this._spec.outerLabel) && void 0 !== _h ? _h : {}; let x1, x2, y1, y2; if (this._isHorizontal()) { const spaceWidth = null !== (_j = outerLabelSpec.spaceWidth) && void 0 !== _j ? _j : FUNNEL_LABEL_SPACE_WIDTH, points = this.getPoints(datum), shapeMiddleHeight = (Math.abs(points[0].y - points[1].y) + Math.abs(points[2].y - points[3].y)) / 2; return "top" === this._spec.outerLabel.position || "bottom" === this._funnelAlign ? (y1 = this._getPolygonCenter(points).y - shapeMiddleHeight / 2 - spaceWidth, y2 = !1 !== outerLabelSpec.alignLabel ? (null == outerLabelMarkBounds ? void 0 : outerLabelMarkBounds.y2) + spaceWidth : y1 - spaceWidth, x1 = this._getPolygonCenter(points).x, y1 - y2 < this._minLabelLineWidth && (y2 = y1 - this._minLabelLineWidth), x2 = x1) : (y1 = this._getPolygonCenter(points).y + shapeMiddleHeight / 2 + spaceWidth, y2 = !1 !== outerLabelSpec.alignLabel ? (null == outerLabelMarkBounds ? void 0 : outerLabelMarkBounds.y1) - spaceWidth : y1 + spaceWidth, x1 = this._getPolygonCenter(points).x, y2 - y1 < this._minLabelLineWidth && (y2 = y1 + this._minLabelLineWidth), x2 = x1), { x1: x1, x2: x2, y1: y1, y2: y2 }; } const points = this.getPoints(datum), shapeMiddleWidth = (Math.abs(points[0].x - points[1].x) + Math.abs(points[2].x - points[3].x)) / 2, labelWidth = (null == labelMarkBounds ? void 0 : labelMarkBounds.x2) - (null == labelMarkBounds ? void 0 : labelMarkBounds.x1) || 0, spaceWidth = null !== (_k = outerLabelSpec.spaceWidth) && void 0 !== _k ? _k : FUNNEL_LABEL_SPACE_WIDTH; return "right" === this._spec.outerLabel.position || "left" === this._funnelAlign ? (x1 = this._getPolygonCenter(points).x + Math.max(labelWidth / 2, shapeMiddleWidth / 2) + spaceWidth, x2 = !1 !== outerLabelSpec.alignLabel ? (null == outerLabelMarkBounds ? void 0 : outerLabelMarkBounds.x1) - spaceWidth : x1 + spaceWidth, y1 = this._getPolygonCenter(points).y, x2 - x1 < this._minLabelLineWidth && (x2 = x1 + this._minLabelLineWidth), y2 = y1) : (x1 = this._getPolygonCenter(points).x - Math.max(labelWidth / 2, shapeMiddleWidth / 2) - spaceWidth, x2 = !1 !== outerLabelSpec.alignLabel ? (null == outerLabelMarkBounds ? void 0 : outerLabelMarkBounds.x2) + spaceWidth : x1 - spaceWidth, y1 = this._getPolygonCenter(points).y, x1 - x2 < this._minLabelLineWidth && (x2 = x1 - this._minLabelLineWidth), y2 = y1), { x1: x1, x2: x2, y1: y1, y2: y2 }; } _computeMaxSize() { var _a; const size = this._isHorizontal() ? this.getLayoutRect().height : this.getLayoutRect().width, maxSize = null !== (_a = this._spec.maxSize) && void 0 !== _a ? _a : FUNNEL_MAX_SIZE; return calcLayoutNumber(maxSize, size); } _computeMinSize() { var _a; const size = this._isHorizontal() ? this.getLayoutRect().height : this.getLayoutRect().width, minSize = null !== (_a = this._spec.minSize) && void 0 !== _a ? _a : FUNNEL_MIN_SIZE; return calcLayoutNumber(minSize, size); } _isHorizontal() { return "left" === this._funnelOrient || "right" === this._funnelOrient; } _isReverse() { return "bottom" === this._funnelOrient || "right" === this._funnelOrient; } getDefaultShapeType() { return "square"; } getActiveMarks() { return [ this._funnelMark ]; } } FunnelSeries.type = SeriesTypeEnum.funnel, FunnelSeries.mark = funnelSeriesMark, FunnelSeries.builtInTheme = { funnel: funnelTheme }, FunnelSeries.transformerConstructor = FunnelSeriesSpecTransformer; export const registerFunnelSeries = () => { registerPolygonMark(), registerTextMark(), registerRuleMark(), Factory.registerSeries(FunnelSeries.type, FunnelSeries), Factory.registerAnimation("funnel", ((params, preset) => Object.assign({ appear: "clipIn" === preset ? void 0 : { type: "fadeIn" } }, FadeInOutAnimation))), registerCartesianGroupClipAnimation(), registerFadeInOutAnimation(); }; //# sourceMappingURL=funnel.js.map