rumble-charts
Version:
Truly declarative React charts components
84 lines (81 loc) • 4.23 kB
JavaScript
import { __rest, __assign } from './external/tslib/tslib.es6.js';
import React, { useState, useRef, useMemo, useEffect } from 'react';
import { timer } from 'd3-timer';
import { interpolate } from 'd3-interpolate';
import './helpers/colorFunc.js';
import 'd3-shape';
import { eases } from './helpers/eases.js';
import { isFunction } from './helpers/isFunction.js';
import { isString } from './helpers/isString.js';
import { isUndefined } from './helpers/isUndefined.js';
import { normalizeSeries } from './helpers/normalizeSeries.js';
import { omitBy } from './helpers/omitBy.js';
import { pick } from './helpers/pick.js';
import { proxyChildren } from './helpers/proxyChildren.js';
/**
* Animates (actually interpolates) your `series` data. Very useful when you want to have
* simple and nice transitions between data state.
*
* As a wrapper it takes `series` obtained from its parent and gives it to its children.
*
* By default, `interpolateProps` list contains all the common props:
* ['series', 'maxX', 'maxY', 'minX', 'minY', 'layerWidth', 'layerHeight'].
* Though, sometimes it makes a lot of sense to interpolate only `series`. Especially, when the
* components wrapped by `<Animate>` are "jumping". Also, you can explicitly define `minY` as a prop
* to make the limits stable (and therefore prevent the "jumping" effect)
*/
function Animate(props) {
var _a = props.interpolateProps, interpolateProps = _a === void 0 ? ['series', 'maxX', 'maxY', 'minX', 'minY', 'layerWidth', 'layerHeight'] : _a, _b = props.duration, duration = _b === void 0 ? 500 : _b, _c = props.ease, ease = _c === void 0 ? 'linear' : _c, _d = props.tag, tag = _d === void 0 ? 'g' : _d, onStart = props.onStart, onEnd = props.onEnd, onCancel = props.onCancel, logFPS = props.logFPS, pickProps = __rest(props, ["interpolateProps", "duration", "ease", "tag", "onStart", "onEnd", "onCancel", "logFPS"]);
var _e = useState(function () { return (__assign(__assign({}, pickProps), normalizeSeries(pickProps))); }), state = _e[0], setState = _e[1];
var prevPropsRef = useRef(props);
var newPropsRef = useRef();
newPropsRef.current = useMemo(function () {
var newProps = Object.keys(pickProps).reduce(function (newProps, propName) {
var _a;
if (pickProps[propName] !== ((_a = prevPropsRef.current) === null || _a === void 0 ? void 0 : _a[propName])) {
newProps[propName] = pickProps[propName];
}
return newProps;
}, {});
return Object.keys(newProps).length > 0 ? newProps : null;
}, [props !== prevPropsRef.current]) || newPropsRef.current;
prevPropsRef.current = props;
useEffect(function () {
var newProps = newPropsRef.current;
if (!newProps) {
return;
}
var interpolate$1 = interpolate(pick(state, interpolateProps), pick(__assign(__assign({}, newProps), normalizeSeries(newProps)), interpolateProps));
var easeFunc = isString(ease) ?
eases[ease] :
(isFunction(ease) ? ease : eases['linear']);
onStart && onStart();
var i = 0;
var _timer = timer(function (p) {
i++;
if (p >= duration) {
p = duration;
setState(function (state) { return (__assign(__assign({}, state), interpolate$1(easeFunc(p / duration)))); });
onEnd && onEnd();
if (logFPS) {
console.warn(i * (1000 / duration) + 'fps; ' + i + ' frames in ' + duration + 'ms');
}
_timer.stop();
}
else {
setState(function (state) { return (__assign(__assign({}, state), interpolate$1(easeFunc(p / duration)))); });
}
});
return function () {
onCancel && onCancel();
_timer.stop();
};
}, [newPropsRef.current]);
return React.createElement(tag, { className: pickProps.className }, proxyChildren(pickProps.children, omitBy(state, isUndefined), {
layerWidth: state.layerWidth,
layerHeight: state.layerHeight,
scaleX: pickProps.scaleX,
scaleY: pickProps.scaleY
}));
}
export { Animate };