UNPKG

rumble-charts

Version:

Truly declarative React charts components

94 lines (91 loc) 3.97 kB
import React, { useRef } from 'react'; import './helpers/colorFunc.js'; import 'd3-shape'; import 'd3-ease'; import { proxyChildren } from './helpers/proxyChildren.js'; import { sortBy } from './helpers/sortBy.js'; /** * Helps to use mouse events. For now supports only `onClick`, `onMouseMove` and `onMouseLeave`. * * This component will be improved and simplified in the future. */ function Handlers(props) { var className = props.className, layerWidth = props.layerWidth, layerHeight = props.layerHeight; var onClick = props.onClick, onMouseMove = props.onMouseMove, onMouseLeave = props.onMouseLeave; var x = props.scaleX.factory(props); var y = props.scaleY.factory(props); var scaleX = props.scaleX.factory(props); var scaleY = props.scaleY.factory(props); var xDomain = x.domain(); var xRange = x.range(); x.domain(xRange); x.range(xDomain); var yDomain = y.domain(); var yRange = y.range(); y.domain(yRange); y.range(yDomain); var rectRef = useRef(); var ratio = Math.abs((y(1) - y(0)) / (x(1) - x(0))); function handleMouseEvent(handler, event) { if (!rectRef.current) { return; } var rect = rectRef.current.getBoundingClientRect(); var left = rect.left, top = rect.top, width = rect.width, height = rect.height; var clientX = event.clientX, clientY = event.clientY; var series = props.series, _a = props.sensitivity, sensitivity = _a === void 0 ? Infinity : _a, _b = props.optimized, optimized = _b === void 0 ? true : _b, layerWidth = props.layerWidth, layerHeight = props.layerHeight; var realX = (clientX - left) * layerWidth / width; var realY = (clientY - top) * layerHeight / height; var _x = x(realX); var _y = y(realY); var closestPoints = []; var minDistance = sensitivity; series === null || series === void 0 ? void 0 : series.forEach(function (series, seriesIndex) { var _a; (_a = series.data) === null || _a === void 0 ? void 0 : _a.forEach(function (point, pointIndex) { var distance; switch (props.distance) { case 'x': distance = Math.abs(point.x - _x); break; case 'y': distance = Math.abs(point.y - _y); break; default: distance = Math.sqrt(Math.pow(Math.abs(point.x - _x) * (ratio || 1), 2) + Math.pow(Math.abs(point.y - _y), 2)); break; } if (!optimized || distance <= minDistance) { minDistance = distance; closestPoints.push({ seriesIndex: seriesIndex, pointIndex: pointIndex, point: point, distance: distance }); } }); }); closestPoints = sortBy(closestPoints, 'distance'); handler({ clientX: realX, clientY: realY, scaleX: scaleX, scaleY: scaleY, x: _x, y: _y, closestPoints: closestPoints, originalEvent: event }); } var children = proxyChildren(props.children, props, { layerWidth: layerWidth, layerHeight: layerHeight, scaleX: props.scaleX, scaleY: props.scaleY }); return React.createElement("g", { className: className, onClick: onClick && handleMouseEvent.bind(null, onClick), onMouseMove: onMouseMove && handleMouseEvent.bind(null, onMouseMove), onMouseLeave: onMouseLeave }, React.createElement("rect", { ref: rectRef, x: 0, y: 0, width: layerWidth, height: layerHeight, fill: 'transparent', stroke: 'transparent' }), children); } export { Handlers };