@data-ui/histogram
Version:
React + d3 library for creating histograms
148 lines (146 loc) • 4.52 kB
JavaScript
import PropTypes from 'prop-types';
import React from 'react';
import { NodeGroup } from 'react-move';
import { AreaClosed, LinePath } from '@vx/shape';
import { curveBasis } from '@vx/curve';
import { Group } from '@vx/group';
import { chartTheme } from '@data-ui/theme';
var propTypes = {
densityData: PropTypes.arrayOf(PropTypes.object).isRequired,
// @TODO shape
fill: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
fillOpacity: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
getX: PropTypes.func.isRequired,
getY: PropTypes.func.isRequired,
horizontal: PropTypes.bool,
keyAccessor: PropTypes.func,
showArea: PropTypes.bool,
showLine: PropTypes.bool,
stroke: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
strokeDasharray: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
strokeLinecap: PropTypes.oneOf(['butt', 'square', 'round', 'inherit']),
strokeWidth: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
xScale: PropTypes.func.isRequired,
yScale: PropTypes.func.isRequired
};
var defaultProps = {
fill: chartTheme.colors.default,
fillOpacity: 0.3,
horizontal: false,
showArea: true,
showLine: true,
stroke: chartTheme.colors.default,
strokeWidth: 2,
strokeDasharray: null,
strokeLinecap: 'round',
keyAccessor: function keyAccessor(d) {
return d.id;
}
};
var INDEX_DELAY_MULTIPLIER = 10;
function AnimatedDensitySeries(_ref) {
var densityData = _ref.densityData,
fill = _ref.fill,
fillOpacity = _ref.fillOpacity,
horizontal = _ref.horizontal,
keyAccessor = _ref.keyAccessor,
getX = _ref.getX,
getY = _ref.getY,
showArea = _ref.showArea,
showLine = _ref.showLine,
stroke = _ref.stroke,
strokeWidth = _ref.strokeWidth,
strokeDasharray = _ref.strokeDasharray,
strokeLinecap = _ref.strokeLinecap,
xScale = _ref.xScale,
yScale = _ref.yScale;
var maxY = Math.max.apply(Math, yScale.range());
return React.createElement(NodeGroup, {
data: densityData,
keyAccessor: keyAccessor,
start: function start(d) {
if (horizontal) return {
x: 0,
y: yScale.invert ? yScale(getY(d)) : getY(d)
};
return {
x: xScale.invert ? xScale(getX(d)) : getX(d),
y: maxY
};
},
enter: function enter(d, i) {
return {
x: [xScale.invert ? xScale(getX(d)) : getX(d)],
y: [yScale.invert ? yScale(getY(d)) : getY(d)],
fill: [d.fill || fill],
stroke: [d.stroke || stroke],
timing: {
duration: 300,
delay: INDEX_DELAY_MULTIPLIER * i
}
};
},
update: function update(d, i) {
return {
x: [xScale.invert ? xScale(getX(d)) : getX(d)],
y: [yScale.invert ? yScale(getY(d)) : getY(d)],
fill: [d.fill || fill],
stroke: [d.stroke || stroke],
timing: {
duration: 300,
delay: INDEX_DELAY_MULTIPLIER * i
}
};
},
leave: function leave(d, i) {
return {
x: xScale.invert ? xScale(getX(d)) : getX(d),
y: horizontal ? 0 : maxY,
timing: {
duration: 300,
delay: INDEX_DELAY_MULTIPLIER / 2 * i
}
};
}
}, function (modifiedData) {
return React.createElement(Group, {
style: {
pointerEvents: 'none'
}
}, showArea && React.createElement(AreaClosed, {
data: modifiedData,
x: function x(d) {
return xScale.invert ? xScale.invert(d.state.x) : d.state.x;
},
y: function y(d) {
return yScale.invert ? yScale.invert(d.state.y) : d.state.y;
},
xScale: xScale,
yScale: yScale,
fill: fill,
fillOpacity: fillOpacity,
stroke: "transparent",
strokeWidth: strokeWidth,
curve: curveBasis
}), showLine && strokeWidth > 0 && React.createElement(LinePath, {
data: modifiedData,
x: function x(d) {
return xScale.invert ? xScale.invert(d.state.x) : d.state.x;
},
y: function y(d) {
return yScale.invert ? yScale.invert(d.state.y) : d.state.y;
},
xScale: xScale,
yScale: yScale,
stroke: stroke,
strokeWidth: strokeWidth,
strokeDasharray: strokeDasharray,
strokeLinecap: strokeLinecap,
curve: curveBasis,
glyph: null
}));
});
}
AnimatedDensitySeries.propTypes = propTypes;
AnimatedDensitySeries.defaultProps = defaultProps;
export default AnimatedDensitySeries;