UNPKG

@visactor/vchart

Version:

charts lib based @visactor/VGrammar

301 lines (292 loc) 19.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.registerBoxplotSeries = exports.BoxPlotSeries = exports.DEFAULT_STROKE_COLOR = exports.DEFAULT_FILL_COLOR = void 0; const attribute_1 = require("../../constant/attribute"), data_1 = require("../../constant/data"), base_1 = require("../../constant/base"), scale_1 = require("../../util/scale"), cartesian_1 = require("../cartesian/cartesian"), type_1 = require("../interface/type"), interface_1 = require("../../compile/mark/interface"), register_1 = require("../../data/register"), vdataset_1 = require("@visactor/vdataset"), box_plot_1 = require("../../data/transforms/box-plot"), box_plot_2 = require("../../constant/box-plot"), tooltip_helper_1 = require("./tooltip-helper"), add_property_1 = require("../../data/transforms/add-property"), data_key_1 = require("../../data/transforms/data-key"), utils_1 = require("../../animation/utils"), config_1 = require("../../animation/config"), box_plot_3 = require("../../mark/box-plot"), symbol_1 = require("../../mark/symbol"), constant_1 = require("./constant"), factory_1 = require("../../core/factory"), vutils_1 = require("@visactor/vutils"), utils_2 = require("../util/utils"), cartesian_2 = require("../../component/axis/cartesian"), data_2 = require("../../compile/data"), animation_1 = require("./animation"), box_plot_4 = require("../../theme/builtin/common/series/box-plot"), space_1 = require("../../util/space"), vscale_1 = require("@visactor/vscale"), box_plot_transformer_1 = require("./box-plot-transformer"), DEFAULT_STROKE_WIDTH = 2, DEFAULT_SHAFT_FILL_OPACITY = .5, DEFAULT_SHAFT_SHAPE = "line"; exports.DEFAULT_FILL_COLOR = "#FFF", exports.DEFAULT_STROKE_COLOR = "#000"; const DEFAULT_OUTLIER_SIZE = 10; class BoxPlotSeries extends cartesian_1.CartesianSeries { constructor() { super(...arguments), this.type = type_1.SeriesTypeEnum.boxPlot, this.transformerConstructor = box_plot_transformer_1.BoxPlotSeriesSpecTransformer, this._bandPosition = 0; } 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, _f, _g; 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 = null !== (_f = this._spec.outliersStyle) && void 0 !== _f ? _f : null === (_g = this._spec.outlier) || void 0 === _g ? void 0 : _g.style; } initMark() { this._boxPlotMark = this._createMark(BoxPlotSeries.mark.boxPlot, { groupKey: this._seriesField, isSeriesMark: !0 }), this._outliersField && (this._outlierMark = this._createMark(BoxPlotSeries.mark.outlier, { key: data_1.DEFAULT_DATA_INDEX, groupKey: this._seriesField }), this._outlierMark.setData(this._outlierData)); } initMarkStyle() { var _a, _b, _c, _d, _e, _f; const boxPlotMark = this._boxPlotMark; if (boxPlotMark) { const commonBoxplotStyles = { lineWidth: this._lineWidth, fill: null !== (_a = this._boxFillColor) && void 0 !== _a ? _a : "line" !== this._shaftShape ? this.getColorAttribute() : exports.DEFAULT_FILL_COLOR, minMaxFillOpacity: this._shaftFillOpacity, stroke: null !== (_b = this._strokeColor) && void 0 !== _b ? _b : "line" !== this._shaftShape ? exports.DEFAULT_STROKE_COLOR : this.getColorAttribute() }; boxPlotMark.setGlyphConfig({ direction: this._direction, shaftShape: this._shaftShape }); const boxPlotMarkStyles = "horizontal" === this._direction ? { y: datum => this._getPosition(this.direction, datum), boxHeight: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._boxWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); }, ruleHeight: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); }, q1q3Height: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._boxWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); }, minMaxHeight: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); } } : { x: datum => this._getPosition(this.direction, datum), boxWidth: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._boxWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); }, ruleWidth: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); }, q1q3Width: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._boxWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); }, minMaxWidth: () => { var _a; return (0, space_1.getActualNumValue)(null !== (_a = this._shaftWidth) && void 0 !== _a ? _a : "100%", this._getMarkWidth()); } }; this.setMarkStyle(boxPlotMark, commonBoxplotStyles, interface_1.STATE_VALUE_ENUM.STATE_NORMAL, attribute_1.AttributeLevel.Series), this.setMarkStyle(boxPlotMark, boxPlotMarkStyles, interface_1.STATE_VALUE_ENUM.STATE_NORMAL, attribute_1.AttributeLevel.Built_In); } const outlierMark = this._outlierMark; outlierMark && this.setMarkStyle(outlierMark, { fill: null !== (_e = null !== (_d = null === (_c = this._outliersStyle) || void 0 === _c ? void 0 : _c.fill) && void 0 !== _d ? _d : this._boxFillColor) && void 0 !== _e ? _e : this.getColorAttribute(), stroke: this.getColorAttribute(), size: (0, vutils_1.isNumber)(null === (_f = this._outliersStyle) || void 0 === _f ? void 0 : _f.size) ? this._outliersStyle.size : 10 }, interface_1.STATE_VALUE_ENUM.STATE_NORMAL, attribute_1.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 => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, this._minField), { bandPosition: this._bandPosition }), scale), q1: datum => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, this._q1Field), { bandPosition: this._bandPosition }), scale), median: datum => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, this._medianField), { bandPosition: this._bandPosition }), scale), q3: datum => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, this._q3Field), { bandPosition: this._bandPosition }), scale), max: datum => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, this._maxField), { bandPosition: this._bandPosition }), scale) }, interface_1.STATE_VALUE_ENUM.STATE_NORMAL, attribute_1.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: datum => this._getPosition(this.direction, datum), x: datum => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, box_plot_2.BOX_PLOT_OUTLIER_VALUE_FIELD), { bandPosition: this._bandPosition }), scale) } : { x: datum => this._getPosition(this.direction, datum), y: datum => (0, scale_1.valueInScaleRange)(dataToPosition(this.getDatumPositionValues(datum, box_plot_2.BOX_PLOT_OUTLIER_VALUE_FIELD), { bandPosition: this._bandPosition }), scale) }; this.setMarkStyle(outlierMark, outlierMarkPositionChannel, interface_1.STATE_VALUE_ENUM.STATE_NORMAL, attribute_1.AttributeLevel.Series); } } initLabelMarkStyle(textMark) { textMark && this.setMarkStyle(textMark, { fill: this.getColorAttribute(), text: datum => datum[this.getMedianField()], z: this._fieldZ ? this.dataToPositionZ.bind(this) : null }); } initData() { if (super.initData(), !this._data) return; (0, register_1.registerDataSetInstanceTransform)(this._dataSet, "foldOutlierData", box_plot_1.foldOutlierData), (0, register_1.registerDataSetInstanceTransform)(this._dataSet, "addVChartProperty", add_property_1.addVChartProperty); const outlierDataView = new vdataset_1.DataView(this._dataSet, { name: `${this.type}_outlier_${this.id}_data` }); outlierDataView.parse([ this.getViewData() ], { type: "dataview" }), outlierDataView.name = `${base_1.PREFIX}_series_${this.id}_outlierData`, outlierDataView.transform({ type: "foldOutlierData", options: { dimensionField: "horizontal" === this._direction ? this._fieldY : this._fieldX, outliersField: this._outliersField, seriesField: this._seriesField } }), outlierDataView.transform({ type: "addVChartProperty", options: { beforeCall: data_key_1.initKeyMap.bind(this), call: data_key_1.addDataKey } }, !1), this._outlierData = new data_2.CompilableData(this._option, outlierDataView); } compileData() { var _a; super.compileData(), null === (_a = this._outlierData) || void 0 === _a || _a.compile(); } viewDataUpdate(d) { var _a; super.viewDataUpdate(d), null === (_a = this._outlierData) || void 0 === _a || _a.updateData(); } init(option) { super.init(option), this.initBoxPlotMarkStyle(); } _getMarkWidth() { var _a; if (this._autoBoxWidth) return this._autoBoxWidth; const bandAxisHelper = "horizontal" === this._direction ? this._yAxisHelper : this._xAxisHelper, depthFromSpec = this._groups ? this._groups.fields.length : 1, bandWidth = null === (_a = bandAxisHelper.getBandwidth) || void 0 === _a ? void 0 : _a.call(bandAxisHelper, depthFromSpec - 1); let width = bandWidth; return (0, vutils_1.isValid)(this._spec.boxWidth) && (width = (0, space_1.getActualNumValue)(this._spec.boxWidth, bandWidth)), (0, vutils_1.isValid)(this._spec.boxMinWidth) && (width = Math.max(width, (0, space_1.getActualNumValue)(this._spec.boxMinWidth, bandWidth))), (0, vutils_1.isValid)(this._spec.boxMaxWidth) && (width = Math.min(width, (0, space_1.getActualNumValue)(this._spec.boxMaxWidth, bandWidth))), this._autoBoxWidth = width, this._autoBoxWidth; } _getPosition(direction, datum) { var _a, _b, _c, _d; let axisHelper, sizeAttribute, dataToPosition; "horizontal" === direction ? (axisHelper = this.getYAxisHelper(), sizeAttribute = "boxHeight", dataToPosition = this.dataToPositionY.bind(this)) : (axisHelper = this.getXAxisHelper(), sizeAttribute = "boxWidth", dataToPosition = this.dataToPositionX.bind(this)); const scale = axisHelper.getScale(0), depth = this._groups ? this._groups.fields.length : 1, bandWidth = null === (_a = axisHelper.getBandwidth) || void 0 === _a ? void 0 : _a.call(axisHelper, depth - 1), size = this._boxPlotMark.getAttribute(sizeAttribute, datum); if (depth > 1 && (0, vutils_1.isValid)(this._spec.boxGapInGroup)) { const groupFields = this._groups.fields, boxGapInGroup = (0, vutils_1.array)(this._spec.boxGapInGroup); let totalWidth = 0, offSet = 0; for (let index = groupFields.length - 1; index >= 1; index--) { const groupField = groupFields[index], groupValues = null !== (_c = null === (_b = axisHelper.getScale(index)) || void 0 === _b ? void 0 : _b.domain()) && void 0 !== _c ? _c : [], groupCount = groupValues.length, gap = (0, space_1.getActualNumValue)(null !== (_d = boxGapInGroup[index - 1]) && void 0 !== _d ? _d : (0, vutils_1.last)(boxGapInGroup), bandWidth), i = groupValues.indexOf(datum[groupField]); index === groupFields.length - 1 ? (totalWidth += groupCount * size + (groupCount - 1) * gap, offSet += i * (size + gap)) : (offSet += i * (totalWidth + gap), totalWidth += totalWidth + (groupCount - 1) * gap); } return scale.scale(datum[groupFields[0]]) + axisHelper.getBandwidth(0) / 2 - totalWidth / 2 + offSet + size / 2; } const continuous = (0, vscale_1.isContinuous)(scale.type || "band"); return dataToPosition(datum) + .5 * bandWidth + (continuous ? -bandWidth / 2 : 0); } onLayoutEnd() { super.onLayoutEnd(), this._autoBoxWidth = null; } _initAnimationSpec(config = {}) { const newConfig = (0, vutils_1.merge)({}, config); return [ "appear", "enter", "update", "exit", "disappear" ].forEach((state => { newConfig[state] && "scaleIn" === newConfig[state].type ? newConfig[state].type = "bar" === this._shaftShape ? "barBoxplotScaleIn" : "boxplotScaleIn" : newConfig[state] && "scaleOut" === newConfig[state].type && (newConfig[state].type = "bar" === this._shaftShape ? "barBoxplotScaleOut" : "boxplotScaleOut"); })), newConfig; } initAnimation() { var _a, _b, _c, _d, _e, _f, _g; const animationParams = (0, utils_2.getGroupAnimationParams)(this); if (this._boxPlotMark) { const newDefaultConfig = this._initAnimationSpec(null === (_a = factory_1.Factory.getAnimationInKey("scaleInOut")) || void 0 === _a ? void 0 : _a()), newConfig = this._initAnimationSpec((0, utils_1.userAnimationConfig)("boxPlot", this._spec, this._markAttributeContext)); this._boxPlotMark.setAnimationConfig((0, utils_1.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((0, utils_1.animationConfig)(null === (_g = factory_1.Factory.getAnimationInKey("scaleInOut")) || void 0 === _g ? void 0 : _g(), outlierMarkUserAnimation, animationParams)); } } initTooltip() { this._tooltipHelper = new tooltip_helper_1.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; } getDefaultShapeType() { return "square"; } getActiveMarks() { return [ this._boxPlotMark ]; } } exports.BoxPlotSeries = BoxPlotSeries, BoxPlotSeries.type = type_1.SeriesTypeEnum.boxPlot, BoxPlotSeries.builtInTheme = { boxPlot: box_plot_4.boxPlot }, BoxPlotSeries.mark = constant_1.boxPlotSeriesMark, BoxPlotSeries.transformerConstructor = box_plot_transformer_1.BoxPlotSeriesSpecTransformer; const registerBoxplotSeries = () => { (0, box_plot_3.registerBoxPlotMark)(), (0, symbol_1.registerSymbolMark)(), (0, config_1.registerScaleInOutAnimation)(), (0, cartesian_2.registerCartesianBandAxis)(), (0, cartesian_2.registerCartesianLinearAxis)(), (0, animation_1.registeBoxPlotScaleAnimation)(), factory_1.Factory.registerSeries(BoxPlotSeries.type, BoxPlotSeries); }; exports.registerBoxplotSeries = registerBoxplotSeries; //# sourceMappingURL=box-plot.js.map