@visactor/vchart
Version:
charts lib based @visactor/VGrammar
557 lines (527 loc) • 32.4 kB
JavaScript
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