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绘制时能获取正确的尺寸:
- 自定义CSS类:
.hidden-by-visibility { visibility: hidden; position: absolute; /* 避免占用布局空间 */ top: 0; left: 0; } .visible { visibility: visible; position: static; }
- 修改
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
相关产品推荐
相关产品推荐

