Chart.js渐变背景浏览器缩放时显示异常问题解决方案
问题描述
使用Chart.js开发图表时配置了渐变背景效果,浏览器缩放比例为100%时渐变背景显示完全正常;但通过快捷键Ctrl++或Ctrl+-调整浏览器缩放比例后,渐变背景无法适配缩放后的画布尺寸,显示效果异常。
复现代码
HTML 代码
<div> <canvas id="myChart"></canvas> </div>
JavaScript 代码
const labels = [ 'January', 'February', 'March', 'April', 'May', 'June', ]; const data = { labels: labels, datasets: [{ label: 'My First dataset', backgroundColor: 'rgb(255, 99, 132)', borderColor: 'rgb(255, 99, 132)', data: [0, 10, 5, 2, 20, 30, 45], }] }; const plugin_gradient = { beforeDraw: function(chart, args, options) { const ctx = chart.ctx; const canvas = chart.canvas; const chartArea = chart.chartArea; var gradientBack = canvas.getContext("2d").createLinearGradient(0, canvas.height, canvas.width, 0); gradientBack.addColorStop(1, "rgba(255, 120, 120, 1)"); gradientBack.addColorStop(.5, "rgba(255, 255, 120, 1)"); gradientBack.addColorStop(0, "rgba(120, 255, 120, 1)"); ctx.fillStyle = gradientBack; ctx.fillRect(chartArea.left, chartArea.bottom, chartArea.right - chartArea.left, chartArea.top - chartArea.bottom); } }; const config = { type: 'line', data: data, plugins: [plugin_gradient], options: {} }; const myChart = new Chart( document.getElementById('myChart'), config );
问题原因
该异常的核心诱因是浏览器缩放时,Canvas的实际渲染像素尺寸和DOM层面读取到的canvas.width/canvas.height属性值存在缩放倍率差。原有代码创建渐变时直接取用了整个Canvas的宽高作为渐变起止坐标,但实际填充渐变的区域是图表内部的chartArea范围,二者坐标不匹配,缩放后偏差会被放大,最终导致渐变显示错位。
修复方案
调整渐变创建逻辑,让渐变的起止坐标和实际填充矩形的坐标范围完全对齐,不再使用整个Canvas的宽高生成渐变,修改后的渐变插件代码如下:
const plugin_gradient = { beforeDraw: function(chart, args, options) { const ctx = chart.ctx; const { chartArea } = chart; // 渐变坐标与填充区域坐标完全对齐,自动适配任意缩放比例 const gradientBack = ctx.createLinearGradient( chartArea.left, chartArea.bottom, chartArea.right, chartArea.top ); gradientBack.addColorStop(1, "rgba(255, 120, 120, 1)"); gradientBack.addColorStop(0.5, "rgba(255, 255, 120, 1)"); gradientBack.addColorStop(0, "rgba(120, 255, 120, 1)"); ctx.save(); ctx.fillStyle = gradientBack; ctx.fillRect( chartArea.left, chartArea.bottom, chartArea.right - chartArea.left, chartArea.top - chartArea.bottom ); ctx.restore(); } };
修复说明
- 渐变生成的坐标范围与后续填充矩形的范围完全一致,从根源上避免缩放带来的坐标偏移
- 新增
ctx.save()和ctx.restore()逻辑,避免自定义填充样式污染Chart.js后续的图表元素绘制流程 - 无需额外监听浏览器缩放事件,Chart.js在缩放触发重绘时会自动执行
beforeDraw钩子,实时适配最新的画布尺寸。
内容的提问来源于stack exchange,提问作者mickna
相关产品推荐
相关产品推荐

