class Sparkline extends React.Component { constructor(props) { super(props) this.xScale = d3.scaleLinear() this.yScale = d3.scaleLinear() this.line = d3.line() this._updateDataTransforms(props) } componentDidMount() { const self = this d3.select(ReactDOM.findDOMNode(this.refs.svg)) .on('mousemove', function() { self._onMouseMove(d3.mouse(this)[0]) }) .on('mouseleave', function() { self._onMouseMove(null) }) } componentWillReceiveNewProps(newProps) { this._updateDataTransforms(newProps) } _updateDataTransforms(props) { const { xAccessor, yAccessor, width, height, data } = props this.xScale.domain([0, data.length]).range([0, width]) this.yScale.domain([0, 10]).range([height, 0]) this.line .x((d, i) => this.xScale(xAccessor(d, i))) .y((d, i) => this.yScale(yAccessor(d, i))) this.bisectByX = d3.bisector(xAccessor).left } _onMouseMove(xPixelPos) { const { data, onHover } = this.props if (xPixelPos === null) { onHover(null, null) } else { const xValue = this.xScale.invert(xPixelPos) const i = this.bisectByX(data, xValue, 1) onHover(data[i], i) } } render() { const { data, width, height, xAccessor, hovered } = this.props const hoveredRender = hovered ? ( ) : null return ( {hoveredRender} ) } } Sparkline.defaultProps = { xAccessor: ({ x }) => x, yAccessor: ({ y }) => y } class Example extends React.Component { constructor(props) { super(props) this.state = { hovered: null } } render() { const { data } = this.props const { hovered } = this.state const value = hovered ? `${hovered.y} is the current value under cursor` : `${data.reduce((s, { y }) => s + y, 0)} is the sum of all the values` // total const divStyle = { color: 'orange', position: 'fixed', top: '50px' } const valueStyle = { position: 'fixed', top: '50px', left: '110px' } return (
this.setState({ hovered })} />
{value}
) } } let data = [ 3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 3, 6, 3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9 ] // Interesting fact: d3.bisect accessors assume your not bisecting by the index. // Duh... data = data.map((y, x) => { return { x, y } }) ReactDOM.render(, document.getElementById('example'))