Chart.js 4.4.2中图表移至不同尺寸容器后无法自适应调整大小
Chart.js v4交换图表容器后尺寸不更新的解决方法
问题场景
两个并排图表分别放在大、小容器中,点击后交换容器位置。该功能在Chart.js v2.9.4可正常自适应尺寸,但升级至v4.4.2后,图表移动后仍保留原尺寸,无法适配新容器。
原始代码
HTML
<div id='chart-container'> <div id='big-chart-container'> <canvas id='chart1'></canvas> </div> <div id='small-chart-container'> <canvas id='chart2'></canvas> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <!--Swapping charts works in chart.js 2--> <!--<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>-->
CSS
#chart-container{ display: flex; width: 60vw; } #big-chart-container{ width: 60%; } #small-chart-container{ width: 30%; }
JavaScript
var canvas1 = document.getElementById('chart1') var canvas2 = document.getElementById('chart2') let bigChartContainer = document.getElementById('big-chart-container'); let smallChartContainer =document.getElementById('small-chart-container'); let data1 = [5,7,6,2,6,8,4,5] let data2 = [4,8,15,16,23,42] let labels1 = [...Array(data1.length).keys()] let labels2 = [...Array(data2.length).keys()] let bigChartID = 'chart1'; function chartClicked(chartID){ if(bigChartID != chartID){ //if small chart is clicked then swap charts let smallChart = document.getElementById(chartID) let bigChart = document.getElementById(bigChartID) bigChartContainer.appendChild(smallChart) smallChartContainer.appendChild(bigChart) bigChartID = chartID } } const bigChart = new Chart(canvas1.getContext('2d'), { type: 'line', data: { labels: labels1, datasets: [{ label: "Chart 1", data: data1 }] }, options: { onClick: function(){ chartClicked('chart1') } } }) const smallChart = new Chart(canvas2.getContext('2d'), { type: 'line', data: { labels: labels2, datasets: [{ label: "Chart 2", data: data2, borderColor: 'rgb(255, 99, 132)', }] }, options: { onClick: function(){ chartClicked('chart2') } } })
原因分析
Chart.js v4移除了v2中自动监听DOM元素移动后尺寸变化的逻辑,默认不会主动重新计算容器尺寸。交换canvas元素后,图表实例仍持有原容器的尺寸信息,需要手动触发尺寸更新。
解决方案
在交换容器后,先强制浏览器重新计算布局(确保容器尺寸已更新),再调用图表实例的resize()方法,让图表自适应新容器的尺寸。
修改后的chartClicked函数如下:
function chartClicked(chartID){ if(bigChartID != chartID){ let smallChartEl = document.getElementById(chartID) let bigChartEl = document.getElementById(bigChartID) // 交换canvas元素 bigChartContainer.appendChild(smallChartEl) smallChartContainer.appendChild(bigChartEl) bigChartID = chartID // 强制浏览器重排,获取最新容器尺寸 void bigChartContainer.offsetWidth; void smallChartContainer.offsetWidth; // 触发图表尺寸更新 bigChart.resize(); smallChart.resize(); } }
原理说明
void element.offsetWidth:读取元素的offsetWidth属性会强制浏览器立即重新计算布局,确保容器的尺寸已经更新为新的状态。chart.resize():Chart.js的实例方法,会重新读取容器的尺寸并调整图表的大小,适配新容器。
内容的提问来源于stack exchange,提问作者user24917036
相关产品推荐
相关产品推荐

