UNPKG

@visactor/vchart

Version:

charts lib based @visactor/VGrammar

310 lines (277 loc) 14.9 kB
import { AttributeLevel } from "../../constant/attribute"; import { DEFAULT_DATA_INDEX } from "../../constant/data"; import { PREFIX } from "../../constant/base"; import { valueInScaleRange } from "../../util/scale"; import { CartesianSeries } from "../cartesian/cartesian"; import { SeriesTypeEnum } from "../interface/type"; import { STATE_VALUE_ENUM } from "../../compile/mark/interface"; import { registerDataSetInstanceTransform } from "../../data/register"; import { DataView } from "@visactor/vdataset"; import { foldOutlierData } from "../../data/transforms/box-plot"; import { BOX_PLOT_OUTLIER_VALUE_FIELD } from "../../constant/box-plot"; import { BoxPlotSeriesTooltipHelper } from "./tooltip-helper"; import { addVChartProperty } from "../../data/transforms/add-property"; import { addDataKey, initKeyMap } from "../../data/transforms/data-key"; import { animationConfig, userAnimationConfig } from "../../animation/utils"; import { registerScaleInOutAnimation } from "../../animation/config"; import { registerBoxPlotMark } from "../../mark/box-plot"; import { registerSymbolMark } from "../../mark/symbol"; import { boxPlotSeriesMark } from "./constant"; import { Factory } from "../../core/factory"; import { merge, isNumber } from "@visactor/vutils"; import { getGroupAnimationParams } from "../util/utils"; import { registerCartesianLinearAxis, registerCartesianBandAxis } from "../../component/axis/cartesian"; import { CompilableData } from "../../compile/data"; import { registeBoxPlotScaleAnimation } from "./animation"; import { boxPlot } from "../../theme/builtin/common/series/box-plot"; const DEFAULT_STROKE_WIDTH = 2, DEFAULT_SHAFT_FILL_OPACITY = .5, DEFAULT_SHAFT_SHAPE = "line"; export const DEFAULT_FILL_COLOR = "#FFF"; export const DEFAULT_STROKE_COLOR = "#000"; const DEFAULT_OUTLIER_SIZE = 10; export class BoxPlotSeries extends CartesianSeries { constructor() { super(...arguments), this.type = SeriesTypeEnum.boxPlot; } getMinField() { return this._minField; } getMaxField() { return this._maxField; } getQ1Field() { return this._q1Field; } getMedianField() { return this._medianField; } getQ3Field() { return this._q3Field; } getOutliersField() { return this._outliersField; } getShaftShape() { return this._shaftShape; } getBoxFillColor() { return this._boxFillColor; } getStrokeColor() { return this._strokeColor; } getOutliersStyle() { return this._outliersStyle; } setAttrFromSpec() { var _a, _b, _c, _d, _e; super.setAttrFromSpec(); const boxPlotStyle = null !== (_b = null === (_a = this._spec.boxPlot) || void 0 === _a ? void 0 : _a.style) && void 0 !== _b ? _b : {}; this._minField = this._spec.minField, this._maxField = this._spec.maxField, this._q1Field = this._spec.q1Field, this._medianField = this._spec.medianField, this._q3Field = this._spec.q3Field, this._outliersField = this._spec.outliersField, this._lineWidth = null !== (_c = boxPlotStyle.lineWidth) && void 0 !== _c ? _c : 2, this._boxWidth = boxPlotStyle.boxWidth, this._shaftShape = null !== (_d = boxPlotStyle.shaftShape) && void 0 !== _d ? _d : "line", this._shaftWidth = boxPlotStyle.shaftWidth, this._boxFillColor = boxPlotStyle.boxFill, this._strokeColor = boxPlotStyle.stroke, this._shaftFillOpacity = "bar" === this._shaftShape ? null !== (_e = boxPlotStyle.shaftFillOpacity) && void 0 !== _e ? _e : .5 : void 0, this._outliersStyle = this._spec.outliersStyle; } initMark() { this._boxPlotMark = this._createMark(BoxPlotSeries.mark.boxPlot, { groupKey: this._seriesField, isSeriesMark: !0 }), this._outliersField && (this._outlierMark = this._createMark(BoxPlotSeries.mark.outlier, { key: DEFAULT_DATA_INDEX, groupKey: this._seriesField, dataView: this._outlierDataView.getDataView(), dataProductId: this._outlierDataView.getProductId() })); } initMarkStyle() { var _a, _b, _c, _d, _e; const boxPlotMark = this._boxPlotMark; if (boxPlotMark) { const commonBoxplotStyles = { lineWidth: this._lineWidth, fill: null !== (_a = this._boxFillColor) && void 0 !== _a ? _a : "line" === this._shaftShape ? "#FFF" : this.getColorAttribute(), minMaxFillOpacity: this._shaftFillOpacity, stroke: null !== (_b = this._strokeColor) && void 0 !== _b ? _b : "line" === this._shaftShape ? this.getColorAttribute() : "#000" }; boxPlotMark.setGlyphConfig({ direction: this._direction, shaftShape: this._shaftShape }); const boxPlotMarkStyles = "horizontal" === this._direction ? Object.assign(Object.assign({ y: this.dataToPositionY.bind(this) }, commonBoxplotStyles), { boxHeight: () => { var _a; return null !== (_a = this._boxWidth) && void 0 !== _a ? _a : this._getMarkWidth(); }, ruleHeight: () => { var _a; return null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : this._getMarkWidth(); }, q1q3Height: () => { var _a; return null !== (_a = this._boxWidth) && void 0 !== _a ? _a : this._getMarkWidth(); }, minMaxHeight: () => { var _a; return null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : this._getMarkWidth(); } }) : Object.assign(Object.assign({ x: this.dataToPositionX.bind(this) }, commonBoxplotStyles), { boxWidth: () => { var _a; return null !== (_a = this._boxWidth) && void 0 !== _a ? _a : this._getMarkWidth(); }, ruleWidth: () => { var _a; return null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : this._getMarkWidth(); }, q1q3Width: () => { var _a; return null !== (_a = this._boxWidth) && void 0 !== _a ? _a : this._getMarkWidth(); }, minMaxWidth: () => { var _a; return null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : this._getMarkWidth(); } }); this.setMarkStyle(boxPlotMark, boxPlotMarkStyles, STATE_VALUE_ENUM.STATE_NORMAL, AttributeLevel.Series); } const outlierMark = this._outlierMark; outlierMark && this.setMarkStyle(outlierMark, { fill: null !== (_d = null === (_c = this._outliersStyle) || void 0 === _c ? void 0 : _c.fill) && void 0 !== _d ? _d : this.getColorAttribute(), size: isNumber(null === (_e = this._outliersStyle) || void 0 === _e ? void 0 : _e.size) ? this._outliersStyle.size : 10, symbolType: "circle" }, STATE_VALUE_ENUM.STATE_NORMAL, AttributeLevel.Series); } initBoxPlotMarkStyle() { var _a, _b; const boxPlotMark = this._boxPlotMark, axisHelper = "horizontal" === this._direction ? this._xAxisHelper : this._yAxisHelper; if (boxPlotMark && axisHelper) { const {dataToPosition: dataToPosition} = axisHelper, scale = null === (_a = null == axisHelper ? void 0 : axisHelper.getScale) || void 0 === _a ? void 0 : _a.call(axisHelper, 0); this.setMarkStyle(boxPlotMark, { min: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, this._minField), { bandPosition: this._bandPosition }), scale), q1: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, this._q1Field), { bandPosition: this._bandPosition }), scale), median: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, this._medianField), { bandPosition: this._bandPosition }), scale), q3: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, this._q3Field), { bandPosition: this._bandPosition }), scale), max: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, this._maxField), { bandPosition: this._bandPosition }), scale) }, STATE_VALUE_ENUM.STATE_NORMAL, AttributeLevel.Series); } const outlierMark = this._outlierMark; if (outlierMark && axisHelper) { const {dataToPosition: dataToPosition} = axisHelper, scale = null === (_b = null == axisHelper ? void 0 : axisHelper.getScale) || void 0 === _b ? void 0 : _b.call(axisHelper, 0), outlierMarkPositionChannel = "horizontal" === this._direction ? { y: this.dataToPositionY.bind(this), x: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, BOX_PLOT_OUTLIER_VALUE_FIELD), { bandPosition: this._bandPosition }), scale) } : { x: this.dataToPositionX.bind(this), y: datum => valueInScaleRange(dataToPosition(this.getDatumPositionValues(datum, BOX_PLOT_OUTLIER_VALUE_FIELD), { bandPosition: this._bandPosition }), scale) }; this.setMarkStyle(outlierMark, outlierMarkPositionChannel, STATE_VALUE_ENUM.STATE_NORMAL, AttributeLevel.Series); } } initData() { if (super.initData(), !this._data) return; registerDataSetInstanceTransform(this._dataSet, "foldOutlierData", foldOutlierData), registerDataSetInstanceTransform(this._dataSet, "addVChartProperty", addVChartProperty); const outlierDataView = new DataView(this._dataSet, { name: `${this.type}_outlier_${this.id}_data` }); outlierDataView.parse([ this.getViewData() ], { type: "dataview" }), outlierDataView.name = `${PREFIX}_series_${this.id}_outlierData`, outlierDataView.transform({ type: "foldOutlierData", options: { dimensionField: "horizontal" === this._direction ? this._fieldY : this._fieldX, outliersField: this._outliersField } }), outlierDataView.transform({ type: "addVChartProperty", options: { beforeCall: initKeyMap.bind(this), call: addDataKey } }, !1), this._outlierDataView = new CompilableData(this._option, outlierDataView); } compileData() { var _a; super.compileData(), null === (_a = this._outlierDataView) || void 0 === _a || _a.compile(); } init(option) { super.init(option), this.initBoxPlotMarkStyle(); } _getMarkWidth() { if (this._autoBoxWidth) return this._autoBoxWidth; const bandAxisHelper = "horizontal" === this._direction ? this._yAxisHelper : this._xAxisHelper, xField = "horizontal" === this._direction ? this._fieldY : this._fieldX, autoBoxWidth = bandAxisHelper.getBandwidth(xField.length - 1) / xField.length; return this._autoBoxWidth = autoBoxWidth, this._autoBoxWidth; } onLayoutEnd() { super.onLayoutEnd(), this._autoBoxWidth = null; } _initAnimationSpec(config = {}) { const newConfig = merge({}, config); return [ "appear", "enter", "update", "exit", "disappear" ].forEach((state => { newConfig[state] && "scaleIn" === newConfig[state].type ? newConfig[state].type = "line" === this._shaftShape ? "boxplotScaleIn" : "barBoxplotScaleIn" : newConfig[state] && "scaleOut" === newConfig[state].type && (newConfig[state].type = "line" === this._shaftShape ? "boxplotScaleOut" : "barBoxplotScaleOut"); })), newConfig; } initAnimation() { var _a, _b, _c, _d, _e, _f, _g; const animationParams = getGroupAnimationParams(this); if (this._boxPlotMark) { const newDefaultConfig = this._initAnimationSpec(null === (_a = Factory.getAnimationInKey("scaleInOut")) || void 0 === _a ? void 0 : _a()), newConfig = this._initAnimationSpec(userAnimationConfig("boxPlot", this._spec, this._markAttributeContext)); this._boxPlotMark.setAnimationConfig(animationConfig(newDefaultConfig, newConfig, animationParams)); } if (this._outlierMark) { const outlierMarkUserAnimation = { appear: null === (_b = this._spec.animationAppear) || void 0 === _b ? void 0 : _b.symbol, disappear: null === (_c = this._spec.animationDisappear) || void 0 === _c ? void 0 : _c.symbol, enter: null === (_d = this._spec.animationEnter) || void 0 === _d ? void 0 : _d.symbol, exit: null === (_e = this._spec.animationExit) || void 0 === _e ? void 0 : _e.symbol, update: null === (_f = this._spec.animationUpdate) || void 0 === _f ? void 0 : _f.symbol }; this._outlierMark.setAnimationConfig(animationConfig(null === (_g = Factory.getAnimationInKey("scaleInOut")) || void 0 === _g ? void 0 : _g(), outlierMarkUserAnimation, animationParams)); } } initTooltip() { this._tooltipHelper = new BoxPlotSeriesTooltipHelper(this), this._boxPlotMark && this._tooltipHelper.activeTriggerSet.mark.add(this._boxPlotMark), this._outlierMark && this._tooltipHelper.activeTriggerSet.mark.add(this._outlierMark); } getStatisticFields() { const fields = super.getStatisticFields(), outliersField = fields.find((f => f.key === this._outliersField)); return outliersField && (outliersField.operations = [ "array-min", "array-max" ]), fields; } onEvaluateEnd(ctx) { super.onEvaluateEnd(ctx), this._outlierDataView.updateData(); } getDefaultShapeType() { return "square"; } getActiveMarks() { return [ this._boxPlotMark ]; } } BoxPlotSeries.type = SeriesTypeEnum.boxPlot, BoxPlotSeries.builtInTheme = { boxPlot: boxPlot }, BoxPlotSeries.mark = boxPlotSeriesMark; export const registerBoxplotSeries = () => { registerBoxPlotMark(), registerSymbolMark(), registerScaleInOutAnimation(), registerCartesianBandAxis(), registerCartesianLinearAxis(), registeBoxPlotScaleAnimation(), Factory.registerSeries(BoxPlotSeries.type, BoxPlotSeries); }; //# sourceMappingURL=box-plot.js.map