UNPKG

@visactor/vmind

Version:

<div align="center"> <a href="https://github.com/VisActor#gh-light-mode-only" target="_blank"> <img alt="VisActor Logo" width="200" src="https://github.com/VisActor/.github/blob/main/profile/logo_500_200_light.svg"/> </a> <a href="https://githu

259 lines (245 loc) 9.94 kB
import { AtomName } from "../../types/atom"; import { BaseAtom } from "../base"; import { isNumber, isValidNumber, merge } from "@visactor/vutils"; import { InsightType } from "../dataInsight/type"; import { getCellFromSpec } from "../../utils/spec"; import { TrendType } from "../dataInsight/algorithms/statistics"; import { isStackChart } from "../dataInsight/utils"; import { Factory } from "../../core/factory"; export class SpecInsightAtom extends BaseAtom { constructor(context, option) { super(context, option), this.name = AtomName.SPEC_INSIGHT, this.isLLMAtom = !1; } buildDefaultContext(context) { return merge({}, { spec: {}, insights: [] }, context); } buildDefaultOptions() { return Object.assign(Object.assign({}, super.buildDefaultOptions()), { defaultMarkerLineStyle: { stroke: "#000", lineWidth: 1, pickStrokeBuffer: 10 }, defaultMarkerSymbolStyle: { fill: "#000", lineWidth: 0, stroke: null }, diffMarkerSymbolStyle: { size: 12, originSymbolType: "arrow", style: { stroke: "#000", fill: !1, lineWidth: 1 } }, labelBackground: { visible: !0, padding: 4, style: { fill: "#3e3e3e", fillOpacity: .85, stroke: "#3e3e3e", lineWidth: 1, cornerRadius: 4 } }, defaultOffsetInGrowthMarkLine: 10 }); } shouldRunByContextUpdate(context) { return !0; } generateMarkPoint(spec, datum, options) { const {direction: direction, text: text, info: info} = options; spec.markPoint || (spec.markPoint = []); const {labelBackground: labelBackground} = this.options, {seriesId: seriesId, seriesIndex: seriesIndex} = info || {}; let offsetX = 0, offsetY = -12; const dOffset = { dx: 0, dy: 8 }; "bottom" === direction ? (offsetY = 12, dOffset.dy = -8) : "top" !== direction && (dOffset.dy = 0, offsetY = 0, "right" === direction ? (offsetX = 12, dOffset.dx = -8) : "left" === direction && (offsetX = -12, dOffset.dx = 8)), spec.markPoint.push(Object.assign(Object.assign(Object.assign({ coordinate: datum }, isNumber(seriesIndex) ? { relativeSeriesIndex: seriesIndex } : {}), seriesId ? { relativeSeriesId: seriesId } : {}), { itemContent: { offsetX: offsetX, offsetY: offsetY, autoRotate: !1, confine: !0, text: Object.assign(Object.assign({ text: text, padding: 4 }, dOffset), { labelBackground: labelBackground, style: { fill: "#fff" } }) }, itemLine: { type: "type-s", arcRatio: .05, startSymbol: { visible: !1 }, endSymbol: { visible: !1 }, line: { style: { lineWidth: 1.5 } } }, targetSymbol: { offset: 0, style: { size: 6, lineWidth: 1 } } })); } formatterValue(value) { const floatValue = Number(value); return floatValue > 10 ? floatValue.toFixed(0) : floatValue >= 1 ? floatValue.toFixed(1) : floatValue >= .1 ? floatValue.toFixed(2) : isValidNumber(floatValue) ? floatValue.toFixed(3) : ""; } getMarkPointText(type, value) { switch (type) { case InsightType.Min: case InsightType.Max: return value ? `${type}: ${value}` : type; case InsightType.TurningPoint: return value ? `Turning Point: ${value}` : "Turning Point"; default: return value ? `Outlier: ${value}` : "Outlier"; } } getAvgMarkLine(spec, value, options) { const {position: position, text: text, info: info} = options; spec.markLine || (spec.markLine = []); const {defaultMarkerLineStyle: defaultMarkerLineStyle, defaultMarkerSymbolStyle: defaultMarkerSymbolStyle, labelBackground: labelBackground} = this.options, {seriesId: seriesId, seriesIndex: seriesIndex} = info || {}; spec.markLine.push(Object.assign(Object.assign(Object.assign({ [position]: value }, isNumber(seriesIndex) ? { relativeSeriesIndex: seriesIndex } : {}), seriesId ? { relativeSeriesId: seriesId } : {}), { label: { visible: !0, autoRotate: !1, text: text, position: "insideEndTop", labelBackground: labelBackground, formatConfig: { content: [ "percentage" ], fixed: 1 }, style: { fill: "#fff", fontSize: 12 } }, line: { style: Object.assign({}, defaultMarkerLineStyle) }, endSymbol: { visible: !0, size: 10, refX: 6, symbolType: "triangleLeft", autoRotate: !1, style: Object.assign({}, defaultMarkerSymbolStyle) } })); } getGrowthMarkLine(spec, options) { spec.markLine || (spec.markLine = []); const {defaultMarkerLineStyle: defaultMarkerLineStyle, defaultMarkerSymbolStyle: defaultMarkerSymbolStyle, defaultOffsetInGrowthMarkLine: defaultOffsetInGrowthMarkLine, labelBackground: labelBackground} = this.options, {coordinates: coordinates, text: text, isTransposed: isTransposed = !1} = options, offset = `${isTransposed ? defaultOffsetInGrowthMarkLine : -defaultOffsetInGrowthMarkLine}%`; spec.markLine.push({ coordinates: coordinates, autoRange: !0, line: { style: Object.assign(Object.assign({}, defaultMarkerLineStyle), { lineDash: [ 0 ] }) }, label: { position: "middle", text: text, labelBackground: labelBackground, style: { fill: "#fff", fontSize: 14 }, pickable: !0, childrenPickable: !1, refY: 0 }, endSymbol: Object.assign({}, defaultMarkerSymbolStyle), coordinatesOffset: [ { x: isTransposed ? offset : 0, y: isTransposed ? 0 : offset }, { x: isTransposed ? offset : 0, y: isTransposed ? 0 : offset } ] }); } runBeforeLLM() { const {spec: spec, insights: insights, chartType: chartType} = this.context, newSpec = merge({}, spec), cell = getCellFromSpec(spec, chartType), pointIndexMap = {}, isStack = isStackChart(spec, chartType, cell); return insights.forEach((insight => { var _a; const {type: type, data: data, value: value, fieldId: fieldId, info: info} = insight, direction = cell.isTransposed ? Number(value) >= 0 ? "right" : "left" : Number(value) >= 0 || !isValidNumber(value) ? "top" : "bottom"; if ([ InsightType.Outlier, InsightType.ExtremeValue, InsightType.MajorityValue, InsightType.TurningPoint ].includes(type) && isStack) return; const formatV = this.formatterValue(value), dataString = JSON.stringify((null === (_a = null == data ? void 0 : data[0]) || void 0 === _a ? void 0 : _a.dataItem) || {}); switch (type) { case InsightType.Min: case InsightType.Max: case InsightType.Outlier: case InsightType.ExtremeValue: case InsightType.MajorityValue: case InsightType.TurningPoint: pointIndexMap[dataString] || (pointIndexMap[dataString] = !0, this.generateMarkPoint(newSpec, Object.assign(Object.assign({}, data[0].dataItem), { [fieldId]: Number(value) }), { direction: direction, text: this.getMarkPointText(type, formatV), info: info })); break; case InsightType.Avg: this.getAvgMarkLine(newSpec, Number(value), { position: cell.isTransposed ? "x" : "y", text: formatV ? `Avg: ${formatV}` : "Avg", info: info }); break; case InsightType.OverallTrend: this.getGrowthMarkLine(newSpec, { coordinates: info.overall.coordinates, isTransposed: cell.isTransposed, text: value === TrendType.INCREASING ? `+${(100 * info.change).toFixed(1)}%` : `${(100 * info.change).toFixed(1)}%` }); } })), this.updateContext({ newSpec: newSpec }), this.context; } } export const registerSpecInsightAtom = () => { Factory.registerAtom(AtomName.SPEC_INSIGHT, SpecInsightAtom); }; //# sourceMappingURL=index.js.map