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

Google Chart切换显示时图表高度异常问题求助

问题:Google饼图切换显示时高度异常

我用React实现了3个展示用户月度消费的Google饼图,通过select下拉框的onChange事件切换显示选中的图表、隐藏其他图表。默认选中的第一个图表高度正常,但切换到另外两个时高度异常。元素检查器显示所有图表的高度都设置为500px,但实际显示不符合预期;尝试过用JS固定高度等方法无效,偶尔刷新后显示正常,但再次刷新又恢复异常。

代码实现

React.useEffect(() => {
    if (months.length > 0) {
        let allDivs = document.querySelectorAll(".montly-category-spending");
        allDivs.forEach(item => {
            // item.classList.add("d-none"); -------- > LINE A
        });

        let div = document.querySelector("#" + selectedMonth);
        div.classList.remove("d-none");
    }
}, [selectedMonth]);

function drawPieDiagram(id) {
    let div = document.querySelector("#" + id);
    let key = id.replace("-", " ");
    let monthData = monthsData[key];

    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Category');
    data.addColumn('number', 'Amount');

    data.addRows(
        Object.entries(monthData).map(([key, value]) => [key, value])
    );

    // Set chart options
    var options = {
        'width': 'auto',
        'height': height,
        'title': `Transactions per category (${key})`,
    };

    console.log(options);
    // Instantiate and draw our chart, passing in some options.
    var chart = new google.visualization.PieChart(div);

    chart.draw(data, options);
}

function handleChange(event) {
    let id = event.currentTarget.value;
    setSelectedMonth(id);
}

return (
    <>
        <div id="google-pie-chart" class="col-12 col-lg-4 p-0">
            {months.map(item => <div id={item} class="montly-category-spending p-0" style={{ height: height }}></div>)}
            <select value={selectedMonth} onChange={handleChange} class="form-select">
                {months.map(item => (
                    <option value={item}>{item.replace('-', ' ')}</option>
                ))}
            </select>
        </div>

    </>
);

现象说明

  • 注释LINE A时:图表堆叠显示,所有图表高度均正常
  • 不注释LINE A时(初始状态):默认选中的第一个图表高度正常,其他图表被隐藏
  • 切换到其他选项时:选中的图表高度异常缩小,显示不符合设置的500px

原因分析

Google Charts在绘制时会读取容器的实际可见尺寸:如果容器初始处于display: none状态(即d-none类),绘制时容器的宽高会被识别为0;即使之后移除隐藏类,图表也不会自动重新计算并调整尺寸。默认第一个图表因为初始可见,绘制时能获取正确的500px高度,而另外两个初始隐藏的图表绘制时尺寸错误,导致切换显示后高度异常。

解决方案

方案1:切换显示后重新绘制对应图表

修改useEffect逻辑,在显示选中的容器后,重新调用drawPieDiagram绘制该图表,确保图表基于当前可见的容器尺寸渲染:

// 监听选中月份变化,切换显示并重绘图表
React.useEffect(() => {
    if (months.length > 0) {
        // 隐藏所有图表容器
        let allDivs = document.querySelectorAll(".montly-category-spending");
        allDivs.forEach(item => {
            item.classList.add("d-none");
        });

        // 显示选中的容器并重新绘制图表
        const targetDiv = document.querySelector("#" + selectedMonth);
        targetDiv.classList.remove("d-none");
        drawPieDiagram(selectedMonth);
    }
}, [selectedMonth]);

// 组件挂载时绘制默认选中的图表
React.useEffect(() => {
    if (months.length > 0 && selectedMonth) {
        drawPieDiagram(selectedMonth);
    }
}, [months, monthsData, selectedMonth]);

方案2:用visibility替代display隐藏容器

使用visibility: hidden替代display: none,这种方式会保留容器的尺寸空间,Google Charts绘制时能获取正确的尺寸:

  1. 自定义CSS类:
.hidden-by-visibility {
    visibility: hidden;
    position: absolute; /* 避免占用布局空间 */
    top: 0;
    left: 0;
}
.visible {
    visibility: visible;
    position: static;
}
  1. 修改useEffect逻辑:
React.useEffect(() => {
    if (months.length > 0) {
        let allDivs = document.querySelectorAll(".montly-category-spending");
        allDivs.forEach(item => {
            item.classList.add("hidden-by-visibility");
            item.classList.remove("visible");
        });

        const targetDiv = document.querySelector("#" + selectedMonth);
        targetDiv.classList.remove("hidden-by-visibility");
        targetDiv.classList.add("visible");
    }
}, [selectedMonth]);

// 组件挂载时绘制所有图表(容器尺寸已存在)
React.useEffect(() => {
    if (months.length > 0) {
        months.forEach(month => drawPieDiagram(month));
    }
}, [months, monthsData]);

方案3:延迟重绘确保DOM更新完成

如果直接重绘不生效,可以添加一个微延迟,等待DOM更新完成后再绘制图表:

React.useEffect(() => {
    if (months.length > 0) {
        let allDivs = document.querySelectorAll(".montly-category-spending");
        allDivs.forEach(item => {
            item.classList.add("d-none");
        });

        const targetDiv = document.querySelector("#" + selectedMonth);
        targetDiv.classList.remove("d-none");
        
        // 等待DOM更新后重绘图表
        setTimeout(() => {
            drawPieDiagram(selectedMonth);
        }, 0);
    }
}, [selectedMonth]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 00:07:59