@data-ui/xy-chart
Version:
A package of charts with standard x- and y- axes. https://williaster.github.io/data-ui
73 lines (66 loc) • 2.61 kB
JavaScript
import { Children } from 'react';
import { localPoint } from '@vx/event';
import findClosestDatum from './findClosestDatum';
import { componentName, isSeries } from './chartUtils';
var DEFAULT_MAX_DISTANCE_PX = 1000;
export default function findClosestDatums(_ref) {
var children = _ref.children,
xScale = _ref.xScale,
yScale = _ref.yScale,
_ref$margin = _ref.margin,
margin = _ref$margin === void 0 ? {} : _ref$margin,
getX = _ref.getX,
getY = _ref.getY,
event = _ref.event,
_ref$maxXDistancePx = _ref.maxXDistancePx,
maxXDistancePx = _ref$maxXDistancePx === void 0 ? DEFAULT_MAX_DISTANCE_PX : _ref$maxXDistancePx;
if (!event || !event.target || !event.target.ownerSVGElement) return null;
var series = {};
var gElement = event.target.ownerSVGElement;
var _localPoint = localPoint(gElement, event),
svgMouseX = _localPoint.x,
svgMouseY = _localPoint.y;
var mouseX = svgMouseX - (margin.left || 0);
var mouseY = svgMouseY - (margin.top || 0);
var closestDatum;
var minDeltaX = Infinity;
var minDeltaY = Infinity;
var flatSeriesChildren = [];
Children.forEach(children, function (Child) {
var name = componentName(Child);
if (name === 'AreaDifferenceSeries') {
Children.forEach(Child.props.children, function (NestedChild) {
flatSeriesChildren.push(NestedChild);
});
} else if (isSeries(name)) {
flatSeriesChildren.push(Child);
}
}); // collect data from all series that have an x value near this point
flatSeriesChildren.forEach(function (Child, childIndex) {
if (!Child.props.disableMouseEvents) {
var _Child$props = Child.props,
data = _Child$props.data,
seriesKey = _Child$props.seriesKey; // @TODO data should be sorted, come up with a way to enforce+cache instead of relying on user
var datum = findClosestDatum({
data: data,
getX: getX,
xScale: xScale,
event: event,
marginLeft: margin.left
});
var deltaX = Math.abs(xScale(getX(datum || {})) - mouseX);
if (datum && deltaX <= maxXDistancePx) {
var key = seriesKey || childIndex; // fall back to child index
series[key] = datum;
var deltaY = Math.abs(yScale(getY(datum)) - mouseY);
closestDatum = deltaY < minDeltaY && deltaX <= minDeltaX ? datum : closestDatum;
minDeltaX = closestDatum === datum ? deltaX : minDeltaX;
minDeltaY = closestDatum === datum ? deltaY : minDeltaY;
}
}
});
return {
series: series,
closestDatum: closestDatum
};
}