Search code examples
reactjstypescripthighchartsreact-highcharts

Is there a way to implement react typescript highcharts mouse zoom in/zoom out?


I am using highcharts in React. I want to implement a zoom-in/zoom-out function when displaying a lot of data, but I don't know how to implement mouse wheel zoom-in/zoom-out in React. help.

import React, { useEffect, useRef, useState } from 'react';
import HighChartsReact from 'highcharts-react-official';
import HighCharts from 'highcharts';
const option = {
    title: {
        text: 'Monthly Average Temperature',
        x: -20, // center
    },
    subtitle: {
        text: 'Source: WorldClimate.com',
        x: -20,
    },
    xAxis: {
        /*
    categories: ['Jan']
*/

    },
    yAxis: {
        title: {
            text: 'Temperature (°C)',
        },
        plotLines: [{
            value: 0,
            width: 1,
            color: '#808080',
        }],
    },
    tooltip: {
        valueSuffix: '°C',
    },
    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle',
        borderWidth: 0,
    },
    series: [{
        name: 'Tokyo',
        data: [],
    }, {
        name: 'New York',
        data: [],
    }, {
        name: 'Berlin',
        data: [],
    }, {
        name: 'London',
        data: [],
    }],
    zoomType: 'x',
};
const HighChartTest = () => {
    const chartComponentRef = useRef<HighChartsReact.RefObject>(null);
    const [options, setoptions] = useState(option);
    let now = new Date(1997, 9, 3);
    let value = Math.random() * 1000;
    const oneDay = 24 * 3600 * 1000;

    const chartData: any = [1, 2, 3, 4, 5];
    const chartData1: any = [1, 2, 3, 4, 5];
    const chartData2: any = [1, 2, 3, 4, 5];
    const chartData3: any = [1, 2, 3, 4, 5];
    for (let i = 0; i < 10000; i++) {
        chartData.push(randomRange(1, 100));
        chartData1.push(randomRange(100, 1000));
        chartData2.push(randomRange(1000, 2000));
        chartData3.push(randomRange(2000, 5000));
    }
    function randomData(key: number) {
        now = new Date(+now + oneDay);
        value = Math.round(Math.random() * key);
        return [ Math.round(value)];
    }
    function randomRange(n1:number, n2:number) {
        return [Math.floor((Math.random() * (n2 - n1 + 1)) + n1)];
    }
    useEffect(() => {
        chartComponentRef.current?.chart.series[0].setData(chartData);
        chartComponentRef.current?.chart.series[1].setData(chartData1);
        chartComponentRef.current?.chart.series[2].setData(chartData2);
        chartComponentRef.current?.chart.series[3].setData(chartData3);
    }, []);
    

    return (
        <div style={{ width: '100%', height: 500 }}>
            <HighChartsReact
                ref={chartComponentRef}
                highcharts={HighCharts}
                options={options}
            />
        </div>
    );
};

export default HighChartTest;

I don't know how to implement the mouse wheel zoom-in/zoom-out function. In js, you can use the code below, but in tsx, a callback error appears. Any solution?

(function(H) {
  HighCharts.Chart.prototype.callbacks.push(function(chart) {
      H.addEvent(chart.container, 'wheel', function(e) {
          const xAxis = chart.xAxis[0],
              extremes = xAxis.getExtremes(),
              newMin = extremes.min;
    
          console.log(extremes);
          console.log(newMin);
    
          if (e.deltaY < 0) {
              xAxis.setExtremes(extremes.min - (extremes.min * 0.001), extremes.max, true);
          } else {
              xAxis.setExtremes(extremes.min + (extremes.min * 0.001), extremes.max, true);
          }
      });
  });
}(HighCharts));

Solution

  • You can add the wheel Highcharts event on chart load and correctly type the function arguments. For example:

    chart: {
      events: {
        load: function(this: Highcharts.Chart){
          const chart = this;
          Highcharts.addEvent(chart.container, 'wheel', function(e: WheelEvent) {
              const xAxis = chart.xAxis[0],
                  extremes = xAxis.getExtremes(),
                  newMin = extremes.min;
        
              console.log(extremes);
              console.log(newMin);
    
              if (e.deltaY < 0) {
                  xAxis.setExtremes(extremes.min - (extremes.min * 0.001), extremes.max, true);
              } else {
                  xAxis.setExtremes(extremes.min + (extremes.min * 0.001), extremes.max, true);
              }
          });
        }
      }
    }
    

    Live demo: https://codesandbox.io/s/react-typescript-79dg6m?file=/src/App.tsx

    API Reference: https://api.highcharts.com/highcharts/chart.events.load