简体   繁体   中英

How do I access & control the selected segment in a plotly.js sunburst chart in React

I have a plotly sunburst chart in my React app (just a simple <plot> react component ). By default, Plotly allows the user to zoom-in on lower levels by clicking on chart segments (see first link for demonstration).

I want to display some contextual data about the "selected" segment elsewhere on the page when a user has clicked on it (while maintaining the default zoom behaviour of the chart).

The idiomatic way to solve this type of problem in React is to use a controlled component , where React dictates the state of the component on render, rather than the component managing the state itself (as Plotly currently does by default).

This would be ideal as in the future I would like to store the state in the URL so that it would be possible to generate links to specific items.

This would seem to require:

  • disabling the default click behaviour
  • storing the selected item in the React state (or elsewhere) when a segment is clicked
  • passing the selection back to Plotly every time the chart is rendered

... but there doesn't appear to be any info about how to do any of these things in the Plotly reference docs.

The zoom behaviour can be monitored using the plotly-sunburstclick event. When using the react <plot> component, this can be monitored using onSunburstClick ( pending pull request ).

The ID of segment that will be navigated to is in the event data as the nextLevel property , which can be used to drive React behaviour (eg using useState ). Note that is important to use this property, and not the ID of the clicked segment, as when the central segment is clicked, the chart will actually navigate up a level to the parent.

To start to bring the zoom level fully under React's control return false from the sunburstclick event handler. This will prevent plotly from perfoming the zoom itself. Note that this will also stop the regular onClick / plotly_click from firing.

onSunburstClick={(event) => {
    doSomethingWith(event.nextLevel)
    return false
}}

You can then manually set the zoom level by setting the level property of the sunburst trace's data .

data={[{
    ...,
    level: /*Level from props or state*/,
    ...
}]}

The zoom is now fully managed by React as if it was a controlled component, but a final piece is missing; the zoom level changes instantly without a smooth transition animation. This can be fixed by manually specifying a transition in the layout , as per this pull request .

layout={{
    ...,
    transition: {
        duration: 1000,
        easing: 'cubic-in-out'
    },
    ...
}}

Here is a complete example that stores the zoom in the component state so the current id can be displayed

const MySunburst = () => {
    const [selected, setSelected] = useState('default id here, usually the root id')

    return <div>
        <span>Currently viewing: {selected}</span>
        <Plot data={[{
            type: "sunburst",
            level: selected,
            labels: // Some labels
            ids: // Some ids
            parents: // Some parents
        }]} layout={{
            transition: {
                duration: 500,
                easing: 'cubic-in-out'
            }
        }} onSunburstClick={(event) => {
            setSelected(event.nextLevel)
            return false
        }}/>
    <div>
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM