@visactor/vchart
Version:
charts lib based @visactor/VGrammar
153 lines (144 loc) • 8.21 kB
JavaScript
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 => {
const {currentValue: currentValue, cacheInfo: cacheInfo, labelsComp: labelsComp, attributes: attributes, coordKey: coordKey} = stateByField[field];
let axis = null, coord = 0;
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;
}
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
};
let bandSize;
newCacheInfo && (newCacheInfo._isCache = useCache);
let offsetSize = 0;
if (attributes && currentValue.forEach((({axis: axis, datum: value = ""}) => {
var _a;
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();
newCacheInfo.labels[axisOrient] && (newCacheInfo.labels[axisOrient].visible = !0,
newCacheInfo.labels[axisOrient].text = value, "left" === axisOrient ? (newCacheInfo.labels[axisOrient].dx = -labelOffset,
newCacheInfo.labelsTextStyle[axisOrient] = {
textAlign: "right",
textBaseline: "middle"
}) : "right" === axisOrient ? (newCacheInfo.labels[axisOrient].dx = labelOffset,
newCacheInfo.labelsTextStyle[axisOrient] = {
textAlign: "left",
textBaseline: "middle"
}) : "top" === axisOrient ? (newCacheInfo.labels[axisOrient].y = 0, newCacheInfo.labels[axisOrient].dy = -labelOffset,
newCacheInfo.labelsTextStyle[axisOrient] = {
textAlign: "center",
textBaseline: "bottom"
}) : "bottom" === axisOrient && (newCacheInfo.labels[axisOrient].dy = labelOffset,
newCacheInfo.labelsTextStyle[axisOrient] = {
textAlign: "center",
textBaseline: "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 extend = getRectSize(attributes, bandSize, cacheInfo.axis), {coordRange: coordRange} = cacheInfo;
positionAttribute = {
visible: !0,
start: {
[coordKey]: Math.max(coord - extend / 2 - offsetSize / 2, coordRange[0]),
[anotherAxisKey]: sizeRange[0]
},
end: {
[coordKey]: Math.min(coord + bandSize + extend / 2 + offsetSize / 2, coordRange[1]),
[anotherAxisKey]: sizeRange[1]
}
};
}
return positionAttribute;
};
const getRectSize = (hair, bandSize, axis) => {
var _a, _b, _c;
let extend = 0;
if (null === (_a = hair.style) || void 0 === _a ? void 0 : _a.sizePercent) extend = (hair.style.sizePercent - 1) * bandSize; else if ("number" == typeof (null === (_b = hair.style) || void 0 === _b ? void 0 : _b.size)) extend = hair.style.size - bandSize; else if ("function" == typeof (null === (_c = hair.style) || void 0 === _c ? void 0 : _c.size)) {
const axisRect = axis.getLayoutRect();
extend = hair.style.size(axisRect, axis) - bandSize;
}
return extend;
};
//# sourceMappingURL=cartesian.js.map