UNPKG

@visactor/vchart

Version:

charts lib based @visactor/VGrammar

187 lines (177 loc) 11.2 kB
import { isContinuous, isDiscrete } from "@visactor/vscale"; import { getDatumByValue } from "./common"; import { getAxisLabelOffset } from "../../axis/util"; import { isValid } from "@visactor/vutils"; import { getFormatFunction } from "../../util"; export const layoutByValue = (stateByField, series, layoutStartPoint, enableRemain = !1) => (layoutStartPoint || (layoutStartPoint = { x: 0, y: 0 }), Object.keys(stateByField).forEach((field => { var _a, _b, _c, _d, _e; const {currentValue: currentValue, cacheInfo: cacheInfo, labelsComp: labelsComp, attributes: attributes, coordKey: coordKey} = stateByField[field]; let axis = null, coord = 0, axisLabel = null; if (currentValue.size) { const item = Array.from(currentValue.values())[0]; coord = item.axis.getScale().scale(item.datum) + item.axis.getLayoutStartPoint()[coordKey] - layoutStartPoint[coordKey], axis = item.axis, axisLabel = null === (_e = null === (_d = null === (_c = null === (_b = null === (_a = axis.getVRenderComponents()[0]) || void 0 === _a ? void 0 : _a.children[0]) || void 0 === _b ? void 0 : _b.children[0]) || void 0 === _c ? void 0 : _c.getChildByName("axis-label-container")) || void 0 === _d ? void 0 : _d.getChildByName("axis-label-container-layer-0")) || void 0 === _e ? void 0 : _e.children[0]; } const isVisible = !!currentValue.size && Number.isFinite(coord) && !Number.isNaN(coord), useCache = enableRemain && !isVisible && isValid(cacheInfo), newCacheInfo = useCache ? cacheInfo : { coordRange: [ 0, 0 ], sizeRange: [ 0, 0 ], coord: coord, labelsTextStyle: {}, labels: labelsComp ? Object.keys(labelsComp).reduce(((res, labelKey) => (res[labelKey] = { visible: !1, text: "", dx: 0, dy: 0 }, res)), {}) : null, visible: isVisible, axis: axis, axisLabel: axisLabel }; let bandSize; newCacheInfo && (newCacheInfo._isCache = useCache); let offsetSize = 0; if (attributes && currentValue.forEach((({axis: axis, datum: value = ""}) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; let niceLabelFormatter = null; const scale = axis.getScale(); if (isDiscrete(scale.type)) bandSize = scale.bandwidth(), 0 === bandSize && scale.step && (offsetSize = scale.step()); else if (isContinuous(scale.type)) { const field1 = "xField" === field ? series.fieldX[0] : series.fieldY[0], field2 = "xField" === field ? series.fieldX2 : series.fieldY2, datum = getDatumByValue(series.getViewData().latestData, +value, field1, field2); if (datum) { const startX = "xField" === field ? series.dataToPositionX(datum) : series.dataToPositionY(datum); field2 ? (bandSize = Math.abs(startX - ("xField" === field ? series.dataToPositionX1(datum) : series.dataToPositionY1(datum))), value = `${datum[field1]} ~ ${datum[field2]}`) : bandSize = 1, coord = startX; } niceLabelFormatter = axis.niceLabelFormatter; } if (newCacheInfo && (null === (_a = attributes.label) || void 0 === _a ? void 0 : _a.visible) && !useCache) { const labelOffset = getAxisLabelOffset(axis.getSpec()), axisOrient = axis.getOrient(), syncAxisLabelAngle = null === (_b = attributes.label) || void 0 === _b ? void 0 : _b.syncAxisLabelAngle; newCacheInfo.labels[axisOrient] && (newCacheInfo.labels[axisOrient].visible = !0, newCacheInfo.labels[axisOrient].text = value, "left" === axisOrient ? (newCacheInfo.labels[axisOrient].dx = -labelOffset, newCacheInfo.labelsTextStyle[axisOrient] = { textAlign: syncAxisLabelAngle && axisLabel && null !== (_c = axisLabel.attribute.textAlign) && void 0 !== _c ? _c : "right", textBaseline: syncAxisLabelAngle && axisLabel && null !== (_d = axisLabel.attribute.textBaseline) && void 0 !== _d ? _d : "middle" }) : "right" === axisOrient ? (newCacheInfo.labels[axisOrient].dx = labelOffset, newCacheInfo.labelsTextStyle[axisOrient] = { textAlign: syncAxisLabelAngle && axisLabel && null !== (_e = axisLabel.attribute.textAlign) && void 0 !== _e ? _e : "left", textBaseline: syncAxisLabelAngle && axisLabel && null !== (_f = axisLabel.attribute.textBaseline) && void 0 !== _f ? _f : "middle" }) : "top" === axisOrient ? (newCacheInfo.labels[axisOrient].y = 0, newCacheInfo.labels[axisOrient].dy = -labelOffset, newCacheInfo.labelsTextStyle[axisOrient] = { textAlign: syncAxisLabelAngle && axisLabel && null !== (_g = axisLabel.attribute.textAlign) && void 0 !== _g ? _g : "center", textBaseline: syncAxisLabelAngle && axisLabel && null !== (_h = axisLabel.attribute.textBaseline) && void 0 !== _h ? _h : "bottom" }) : "bottom" === axisOrient && (newCacheInfo.labels[axisOrient].dy = labelOffset, newCacheInfo.labelsTextStyle[axisOrient] = { textAlign: syncAxisLabelAngle && axisLabel && null !== (_j = axisLabel.attribute.textAlign) && void 0 !== _j ? _j : "center", textBaseline: syncAxisLabelAngle && axisLabel && null !== (_k = axisLabel.attribute.textBaseline) && void 0 !== _k ? _k : "top" }), newCacheInfo.labels[axisOrient].defaultFormatter = niceLabelFormatter); } })), newCacheInfo && !useCache) { const region = { x1: 1 / 0, y1: 1 / 0, x2: -1 / 0, y2: -1 / 0 }; setRegionArea(region, currentValue), "xField" === field ? (newCacheInfo.coordRange = [ region.x1, region.x2 ], newCacheInfo.sizeRange = [ region.y1, region.y2 ], newCacheInfo.coord = coord + layoutStartPoint.x, newCacheInfo.labels && (newCacheInfo.labels.top.y = region.y1, newCacheInfo.labels.bottom.y = region.y2)) : (newCacheInfo.coordRange = [ region.y1, region.y2 ], newCacheInfo.sizeRange = [ region.x1, region.x2 ], newCacheInfo.coord = coord + layoutStartPoint.y, newCacheInfo.labels && (newCacheInfo.labels.left.x = region.x1, newCacheInfo.labels.right.x = region.x2)), (newCacheInfo.coord < newCacheInfo.coordRange[0] || newCacheInfo.coord > newCacheInfo.coordRange[1]) && (newCacheInfo.visible = !1), attributes && attributes.label && Object.keys(newCacheInfo.labels).forEach((labelKey => { newCacheInfo.labels[labelKey].visible && setFormattedCrosshairLabel(newCacheInfo.labels[labelKey], labelKey, attributes.label); })); } stateByField[field].bandSize = null != bandSize ? bandSize : 0, stateByField[field].offsetSize = offsetSize, stateByField[field].cacheInfo = newCacheInfo; })), stateByField); const setFormattedCrosshairLabel = (labelInfo, position, labelSpec) => { const {formatMethod: formatMethod, formatter: formatter} = labelSpec, {formatFunc: formatFunc, args: args} = getFormatFunction(formatMethod, formatter, labelInfo.text, { label: labelInfo.text, position: position }); formatFunc ? labelInfo.text = formatFunc(...args) : labelInfo.defaultFormatter && (labelInfo.text = labelInfo.defaultFormatter(labelInfo.text)); }, setRegionArea = (outRegion, currentValue) => { currentValue.forEach((({axis: axis}) => { axis.getRegions().forEach((r => { const {x: x, y: y} = r.getLayoutStartPoint(), {width: width, height: height} = r.getLayoutRect(); outRegion.x1 = Math.min(outRegion.x1, x), outRegion.y1 = Math.min(outRegion.y1, y), outRegion.x2 = Math.max(outRegion.x2, x + width), outRegion.y2 = Math.max(outRegion.y2, y + height); })); })); }; export const layoutCrosshair = stateItem => { const {cacheInfo: cacheInfo, attributes: attributes, bandSize: bandSize, offsetSize: offsetSize, coordKey: coordKey, anotherAxisKey: anotherAxisKey} = stateItem, {coord: coord, sizeRange: sizeRange} = cacheInfo, type = attributes.type; let positionAttribute; if ("line" === type) { const pos = coord + bandSize / 2; positionAttribute = { visible: !0, start: { [coordKey]: pos, [anotherAxisKey]: sizeRange[0] }, end: { [coordKey]: pos, [anotherAxisKey]: sizeRange[1] } }; } else if ("rect" === type) { const [offset0, offset1] = getRectSize(attributes, bandSize, offsetSize, cacheInfo.axis), {coordRange: coordRange} = cacheInfo; positionAttribute = { visible: !0, start: { [coordKey]: Math.max(coord + offset0, coordRange[0]), [anotherAxisKey]: sizeRange[0] }, end: { [coordKey]: Math.min(coord + offset1, coordRange[1]), [anotherAxisKey]: sizeRange[1] } }; } return positionAttribute; }; const getRectSize = (hair, bandSize, offsetSize, axis) => { var _a, _b, _c; const visualSize = 0 === bandSize ? offsetSize : bandSize; let size = visualSize; if (null === (_a = hair.style) || void 0 === _a ? void 0 : _a.sizePercent) size = visualSize * hair.style.sizePercent; else if ("number" == typeof (null === (_b = hair.style) || void 0 === _b ? void 0 : _b.size)) size = hair.style.size; else if ("function" == typeof (null === (_c = hair.style) || void 0 === _c ? void 0 : _c.size)) { const axisRect = axis.getLayoutRect(); size = hair.style.size(axisRect, axis); } return 0 === bandSize ? [ -size / 2, size / 2 ] : [ bandSize / 2 - size / 2, size / 2 + bandSize / 2 ]; }; export const getCartesianCrosshairRect = (dimensionData, layoutStartPoint) => { var _a; const currValueX = new Map, currValueY = new Map, {series: series, datum: datum} = dimensionData, isHorizontal = "horizontal" === series.direction, axisId = (isHorizontal ? series.getYAxisHelper() : series.getXAxisHelper()).getAxisId(), axis = series.getChart().getComponentsByKey("axes").find((axis => axis.id === axisId)); if (!axis) return; (isHorizontal ? currValueY : currValueX).set(axis.getSpecIndex(), { datum: null === (_a = series.getDatumPositionValues(datum[0], series.getDimensionField())) || void 0 === _a ? void 0 : _a[0], axis: axis }); const state = { xField: { coordKey: "x", anotherAxisKey: "y", currentValue: currValueX, attributes: { visible: !!currValueX.size, type: "rect" } }, yField: { coordKey: "y", anotherAxisKey: "x", currentValue: currValueY, attributes: { visible: !!currValueY.size, type: "rect" } } }; return layoutByValue(state, series, layoutStartPoint), state.xField.cacheInfo ? layoutCrosshair(state.xField) : state.yField.cacheInfo ? layoutCrosshair(state.yField) : void 0; }; //# sourceMappingURL=cartesian.js.map