You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript中Highcharts鼠标滚轮缩放功能实现求助

React + Highcharts 实现鼠标滚轮缩放(TSX适配方案)

问题

在React+TypeScript项目中使用Highcharts展示大量数据时,需要实现鼠标滚轮缩放功能。现有JavaScript版本的实现代码,但移植到TSX中出现回调类型错误,无法正常运行。

问题根源

原JS代码通过全局修改HighCharts.Chart.prototype.callbacks注册回调,在TS中会触发类型检查错误;另外原缩放逻辑依赖extremes.min的数值计算,当x轴为时间轴或min为0/负数时会出现异常。

解决方案

采用组件内局部监听的方式,通过React ref获取Highcharts实例,添加滚轮事件监听,同时修复缩放逻辑,确保适配各种x轴类型,并且符合TS类型规范。

核心优化点

  • 避免全局修改Highcharts原型,改用组件内实例绑定事件,解决TS类型冲突
  • 基于当前可视范围比例计算缩放增量,替换原依赖extremes.min的不合理逻辑
  • 添加事件销毁逻辑,防止组件卸载后内存泄漏
  • 阻止页面滚动默认行为,避免滚轮事件冲突

完整TSX代码

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: {
        type: 'linear' // 明确x轴类型,适配大数据线性场景
    },
    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);

    // 生成测试数据
    const chartData: number[] = [1, 2, 3, 4, 5];
    const chartData1: number[] = [1, 2, 3, 4, 5];
    const chartData2: number[] = [1, 2, 3, 4, 5];
    const chartData3: number[] = [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 randomRange(n1: number, n2: number): number {
        return Math.floor((Math.random() * (n2 - n1 + 1)) + n1);
    }

    useEffect(() => {
        const chart = chartComponentRef.current?.chart;
        if (!chart) return;

        // 设置图表数据
        chart.series[0].setData(chartData);
        chart.series[1].setData(chartData1);
        chart.series[2].setData(chartData2);
        chart.series[3].setData(chartData3);

        // 滚轮缩放处理函数
        const handleWheel = (e: Event) => {
            e.preventDefault(); // 阻止页面滚动冲突
            const wheelEvent = e as WheelEvent;
            const xAxis = chart.xAxis[0];
            const extremes = xAxis.getExtremes();
            const range = extremes.max - extremes.min;
            const step = range * 0.05; // 每次缩放5%的可视范围

            if (wheelEvent.deltaY < 0) {
                // 向上滚轮:放大(缩小可视范围)
                xAxis.setExtremes(extremes.min + step, extremes.max - step, true);
            } else {
                // 向下滚轮:缩小(扩大可视范围)
                xAxis.setExtremes(extremes.min - step, extremes.max + step, true);
            }
        };

        // 添加滚轮事件监听
        chart.container.addEventListener('wheel', handleWheel);

        // 组件卸载时移除事件,防止内存泄漏
        return () => {
            chart.container.removeEventListener('wheel', handleWheel);
        };
    }, []);

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

export default HighChartTest;

内容的提问来源于stack exchange,提问作者LeeHoSeop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 18:01:21