diff --git a/README.md b/README.md index ebabfad..1bf1f51 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + React-PlotlyJS [![npm version](https://badge.fury.io/js/react-plotlyjs.svg)](http://badge.fury.io/js/react-plotlyjs) ============= @@ -11,14 +12,17 @@ This is a very early, simple wrapper with the following problems: However it does support event handling via the onClick, onBeforeHover, onHover, onUnHover and onSelected props. Note that currently, however, changes to these event handlers after initial creation will not be propogated. + + +## Getting started + As the full Plotly bundle is huge, this library lets you pass a custom bundle to create the component. Therefore you will need Plotly as a direct dependancy of your project. ```javascript -import createPlotlyComponent from 'react-plotlyjs'; +import PlotlyComponent from 'react-plotlyjs'; //See the list of possible plotly bundles at https://github.com/plotly/plotly.js/blob/master/dist/README.md#partial-bundles or roll your own import Plotly from 'plotly.js/dist/plotly-cartesian'; -const PlotlyComponent = createPlotlyComponent(Plotly); ``` Here's a simple example render method: @@ -62,9 +66,65 @@ Here's a simple example render method: displayModeBar: true }; return ( - + + ); + } +``` + + + +## Event Handling + +To add some interaction to the graph, you can use the following handlers: + +- onClick(data, graphDiv) +- onBeforeHover(graphDiv) +- onHover(data, graphDiv) +- onUnHover(data, graphDiv) +- onSelected(eventData, graphDiv) + +For more information, see https://plot.ly/javascript/plotlyjs-events/. + +```javascript + +function handler(data, graphDiv){ + var pn='', + tn='', + colors=[]; + for(var i=0; i < data.points.length; i++){ + pn = data.points[i].pointNumber; + tn = data.points[i].curveNumber; + colors = data.points[i].data.marker.color; + }; + colors[pn] = '#C54C82'; + + var update = {'marker':{color: colors, size:16}}; + Plotly.restyle(graphDiv, update, [tn]); +}); + +render() { + let data = [ + ... + ]; + let layout = { + ... + }; + let config = { + ... + }; + return ( + ); } +``` + + +## Resize with window + +To make the plot redraw when the window size changes, you can use the `resizeWithWindow` prop. + +```javascript +*/resizeWithWindow data={data} layout={layout} config={config} onClick={handler}/> ``` diff --git a/src/PlotlyComponent.js b/src/PlotlyComponent.js index 6c409a1..e169a94 100644 --- a/src/PlotlyComponent.js +++ b/src/PlotlyComponent.js @@ -1,70 +1,69 @@ -import React from 'react'; -import cloneDeep from 'lodash.clonedeep'; +import React from 'react' +import cloneDeep from 'lodash.clonedeep' +import PropTypes from 'prop-types' -let createPlotlyComponent = (plotlyInstance) => React.createClass({ - displayName: 'Plotly', - propTypes: { - data: React.PropTypes.array, - layout: React.PropTypes.object, - config: React.PropTypes.object, - onClick: React.PropTypes.func, - onBeforeHover: React.PropTypes.func, - onHover: React.PropTypes.func, - onUnHover: React.PropTypes.func, - onSelected: React.PropTypes.func - }, - - attachListeners: function() { - if (this.props.onClick) - this.container.on('plotly_click', this.props.onClick); - if (this.props.onBeforeHover) - this.container.on('plotly_beforehover', this.props.onBeforeHover); - if (this.props.onHover) - this.container.on('plotly_hover', this.props.onHover); - if (this.props.onUnHover) - this.container.on('plotly_unhover', this.props.onUnHover); - if (this.props.onSelected) - this.container.on('plotly_selected', this.props.onSelected); - }, +class PlotlyComponent extends React.Component { + attachListeners () { + if (this.props.onClick) { this.container.on('plotly_click', (data) => this.props.onClick(data, this.container)) } + if (this.props.onBeforeHover) { this.container.on('plotly_beforehover', () => this.props.onBeforeHover(this.container)) } + if (this.props.onHover) { this.container.on('plotly_hover', (data) => this.props.onHover(data, this.container)) } + if (this.props.onUnHover) { this.container.on('plotly_unhover', (data) => this.props.onUnHover(data, this.container)) } + if (this.props.onSelected) { this.container.on('plotly_selected', (eventData) => this.props.onSelected(eventData, this.container)) } + } - shouldComponentUpdate(nextProps) { - //TODO logic for detecting change in props - return true; - }, + shouldComponentUpdate (nextProps) { + // TODO logic for detecting change in props + return true + } - componentDidMount() { - let {data, layout, config} = this.props; - plotlyInstance.newPlot(this.container, data, cloneDeep(layout), config); //We clone the layout as plotly mutates it. - this.attachListeners(); - }, + componentDidMount () { + let {data, layout, config, plotly} = this.props + plotly.newPlot(this.container, data, cloneDeep(layout), config) // We clone the layout as plotly mutates it. + if (this.props.resizeWithWindow) window.addEventListener('resize', this.resize.bind(this)) + this.attachListeners() + } - componentDidUpdate(prevProps) { - //TODO use minimal update for given changes + componentDidUpdate (prevProps) { + // TODO use minimal update for given changes if (prevProps.data !== this.props.data || prevProps.layout !== this.props.layout) { - plotlyInstance.newPlot(this.container, this.props.data, this.props.layout); - this.attachListeners(); + this.props.plotly.newPlot(this.container, this.props.data, this.props.layout) + this.attachListeners() } - }, + } - componentWillUnmount: function() { - plotlyInstance.purge(this.container); - }, + componentWillUnmount () { + if (this.props.resizeWithWindow) window.removeEventListener('resize', this.resize.bind(this)) + this.props.plotly.purge(this.container) + } - resize: function() { - plotlyInstance.Plots.resize(this.container); - }, + resize () { + this.props.plotly.Plots.resize(this.container) + } - render: function () { - let {data, layout, config, ...other } = this.props; - //Remove props that would cause React to warn for unknown props. - delete other.onClick; - delete other.onBeforeHover; - delete other.onHover; - delete other.onUnHover; - delete other.onSelected; + render () { + let { plotly, data, layout, config, ...other } = this.props + // Remove props that would cause React to warn for unknown props. + delete other.onClick + delete other.onBeforeHover + delete other.onHover + delete other.onUnHover + delete other.onSelected - return
this.container=node} /> + return
this.container = node} /> } -}); +} + +PlotlyComponent.propTypes = { + plotly: PropTypes.object, + data: PropTypes.array, + layout: PropTypes.object, + config: PropTypes.object, + onClick: PropTypes.func, + onBeforeHover: PropTypes.func, + onHover: PropTypes.func, + onUnHover: PropTypes.func, + onSelected: PropTypes.func, + resizeWithWindow: PropTypes.bool +} -export default createPlotlyComponent; +export default PlotlyComponent