Svelte应用中Chart.js图表无法随浏览器窗口响应的问题求助
在Svelte中实现Chart.js响应式图表的问题
我想在Svelte应用里用Chart.js做一个能随浏览器窗口大小变化的响应式图表。现在把图表放在div容器里,但容器尺寸能随窗口变化,canvas却不行——放大窗口图表不跟着变大,缩小也不同步缩小。我试过手动控制canvas尺寸,但没解决问题:
const clientHeight = document.getElementsByClassName('chart-container')[0].clientHeight; const clientWidth = document.getElementsByClassName('chart-container')[0].clientWidth; chart.canvas.height = clientHeight; chart.canvas.width = clientWidth;
我的完整代码如下:
<script> import { onMount } from 'svelte'; import Chart from 'chart.js/auto'; let data = [20, 100, 50, 12, 20, 130, 45]; let labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; let ctx; let canvas; onMount(() => { ctx = canvas.getContext('2d'); var chart = new Chart(ctx, { options: { layout: { responsive: true, maintainAspectRatio: false } }, type: 'bar', data: { labels: labels, datasets: [ { label: 'Unit Sales', data: data } ] } }); }); </script> <div class="chart-container"> <canvas bind:this={canvas} /> </div> <style> div { position: relative; height: 100vh; width: 100vw; } </style>
请问还有什么办法解决这个问题?
解决方法
1. 修正Chart.js响应式配置的位置
你已经设置了responsive: true和maintainAspectRatio: false,但这两个属性是options下的顶级配置,不能嵌套在layout对象里。调整代码如下:
var chart = new Chart(ctx, { options: { responsive: true, maintainAspectRatio: false, // 其他配置项 }, // 图表类型、数据等其他参数 });
错误的嵌套位置会导致Chart.js无法识别响应式配置,这是核心问题之一。
2. 监听窗口resize事件并触发图表重绘
即使配置正确,Svelte的DOM更新和Chart.js的响应式触发可能不同步,需要手动监听窗口大小变化,调用图表的resize()方法:
修改onMount中的代码,添加resize监听:
onMount(() => { const ctx = canvas.getContext('2d'); const chart = new Chart(ctx, { options: { responsive: true, maintainAspectRatio: false }, type: 'bar', data: { labels: labels, datasets: [{ label: 'Unit Sales', data: data }] } }); // 监听窗口resize const handleResize = () => { chart.resize(); }; window.addEventListener('resize', handleResize); // 组件销毁时清理监听和图表实例,避免内存泄漏 return () => { window.removeEventListener('resize', handleResize); chart.destroy(); }; });
3. 给canvas设置占满容器的样式
Chart.js会自动给canvas生成内联样式,需要强制让它继承容器尺寸:
.chart-container canvas { width: 100% !important; height: 100% !important; }
完整修正后的代码
<script> import { onMount } from 'svelte'; import Chart from 'chart.js/auto'; let data = [20, 100, 50, 12, 20, 130, 45]; let labels = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; let canvas; onMount(() => { const ctx = canvas.getContext('2d'); const chart = new Chart(ctx, { options: { responsive: true, maintainAspectRatio: false }, type: 'bar', data: { labels: labels, datasets: [{ label: 'Unit Sales', data: data }] } }); const handleResize = () => { chart.resize(); }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); chart.destroy(); }; }); </script> <div class="chart-container"> <canvas bind:this={canvas} /> </div> <style> .chart-container { position: relative; height: 100vh; width: 100vw; } .chart-container canvas { width: 100% !important; height: 100% !important; } </style>
内容的提问来源于stack exchange,提问作者andrewshih
相关产品推荐
相关产品推荐

