Issue with Saving and Restoring Zoom State in Kendo React Charts

1 Answer 91 Views
Charts
Martí
Top achievements
Rank 1
Martí asked on 29 Jul 2024, 12:45 PM

I am encountering an issue with saving and restoring the zoom state in the Kendo React Charts component. The problem arises when I attempt to save the zoom level and reapply it whenever the chart data updates. Although the zoom state values are captured correctly, the chart resets to its default zoom level after each zoom interaction.

This is the parent Component:

function Monitor () {
  const { chartDataByParameter, treshholdRangeData } = useTable()
  const [zoomState, setZoomState] = useState({})

  const handleZoomChange = (newZoomState) => {
    setZoomState(newZoomState)
  }

  return 
          <ChartComponent dataProps={chartDataByParameter} rangeData={treshholdRangeData} zoomState={zoomState} onZoomChange={handleZoomChange} />
}

export default Monitor


And this is the Chart Component. Note that i have two axis because is the only way I found to deal with negative values.

function ChartComponent ({ dataProps, rangeData, zoomState, onZoomChange }) {
  const chartRef = useRef(null)

  useEffect(() => {
    setIsChartLoading(false)
    if (chartRef.current && chartRef.current.kendoChart) {
      chartRef.current.kendoChart.setOptions({
        categoryAxis: {
          min: zoomState.xAxis.min,
          max: zoomState.xAxis.max
        },
        valueAxis: {
          min: zoomState.valueAxis.min,
          max: zoomState.valueAxis.max
        }
      })
    }
  }, [dataProps])

  const handleZoom = (event) => {
    const newZoomState = {
      xAxis: {
        min: event.axisRanges?.xAxis?.min,
        max: event.axisRanges?.xAxis?.max
      },
      valueAxis: {
        min: event.axisRanges?.valueAxis?.min,
        max: event.axisRanges?.valueAxis?.max
      }
    }
    onZoomChange(newZoomState)
  }

  const colors = ['#718ad5', '#424242', '#ffe162', '#4cd180', '#8634b7']
  const categoryAxisMaxDivisions = 10


  return (
<div style={{ height: '55vh, width: '100%' }}>
      {(dataProps && dataProps.length > 0) || (rangeData && rangeData.length > 0)
        ? (
        <Chart
          ref={chartRef}
          style={{ height: '100%', width: '100%' }}
          pannable={true}
          zoomable={true}
          transitions={false}
          className='custom-chart'
          onZoom={handleZoom}
        >
          <ChartLegend position="top" />
          <ChartCategoryAxis>
            <ChartCategoryAxisItem name="xAxis" maxDivisions={categoryAxisMaxDivisions} visible={false} />
            <ChartCategoryAxisItem name="xAxis2" maxDivisions={categoryAxisMaxDivisions} />
          </ChartCategoryAxis>
          <ChartSeries>
            {dataProps.map((item, index) => (
              <ChartSeriesItem
                key={index}
                type="line"
                data={item}
                field="value"
                categoryField="category"
                name={item[0].parameter}
                style="smooth"
                color={item[0].parameter === 'Anomalies' ? '#d75d5d' : colors[index]}
                width={item[0].parameter === 'Anomalies' ? 0 : 2}
                legendItem={item[0].parameter === 'Anomalies' ? customLegendItem : customLegendItem2}
                tooltip={{ visible: true, render: lineTooltipRender }}
              />
            ))}
            {rangeData.length > 0 && (
              <ChartSeriesItem
                type="rangeArea"
                data={rangeData}
                fromField="min"
                toField="max"
                categoryField="Datetime"
                name="Anomaly sensitivity"
                color='#80cf63'
              >
                <ChartTooltip render={rangeTooltipRender} />
              </ChartSeriesItem>
            )}
          </ChartSeries>
          <ChartValueAxis>
            <ChartValueAxisItem
              name="valueAxis"
              axisCrossingValue={[0, Number.NEGATIVE_INFINITY]}
              labels={{ format: (value) => value.toFixed(2) }}
            />
          </ChartValueAxis>
        </Chart>
          )
        : (
        <div style={{ height: chartHeight, width: '100%' }}></div>
          )}
    </div>
  )
}
}

const MemoizedChartComponent = React.memo(ChartComponent)
export default MemoizedChartComponent

Thank you in advance!

Xavier

1 Answer, 1 is accepted

Sort by
0
Konstantin Dikov
Telerik team
answered on 31 Jul 2024, 07:59 AM

Hello Xavier,

I would suggest adding the logic that sets the min/max values within a setTimeout function and see if that will have any effect.

If the issue persists, please share a stackblitz example that we can test and debug locally and also, elaborate which version of the Chart component you are using.

Looking forward to your reply.

 

Regards,
Konstantin Dikov
Progress Telerik

Do you have a stake in the designеr-developer collaboration process? If so, take our survey to share your perspective and become part of this global research. You’ll be among the first to know once the results are out.
-> Start The State of Designer-Developer Collaboration Survey 2024

Martí
Top achievements
Rank 1
commented on 02 Aug 2024, 11:44 AM

Hi Konstantin,

Thanks for your prompt response.

I tried using setTimeOut but the issue persisted. Even after the specified milliseconds, the chart zoom continued to reset to the default value.

Finally i solved using a ref, like this:

  const handleZoomOrPan = (event) => {
    const min = !useMultipleAxes ? event.axisRanges.sharedAxis.min : event.axisRanges.valueAxis0.min
    const max = !useMultipleAxes ? event.axisRanges.sharedAxis.min : event.axisRanges.valueAxis0.max
    zoomRef.current = { min, max }
  }

So now i can access zoomRef.current.min :)

Tags
Charts
Asked by
Martí
Top achievements
Rank 1
Answers by
Konstantin Dikov
Telerik team
Share this question
or