如何实现Canvas图表图例文本的移动端响应式适配?
Hey there! 我之前也遇到过Canvas图表移动端图例文本的响应式适配问题,分享几个亲测有效的方案给你:
1. 基于视口宽度动态调整字体大小
这是最直接的方案——通过监听窗口resize事件,根据当前视口宽度动态计算图例文本的字体大小,还能设置最小字体避免文本过小:
// 初始化时先执行一次适配 adjustLegendFontSize(); // 监听窗口尺寸变化 window.addEventListener('resize', adjustLegendFontSize); function adjustLegendFontSize() { const viewportWidth = window.innerWidth; const baseFontSize = 14; // 桌面端默认字体大小 const mobileBreakpoint = 768; // 移动端断点(可根据你的需求调整) const minFontSize = 10; // 最小字体,防止文本太小看不清 // 计算适配后的字体大小 let fontSize = baseFontSize; if (viewportWidth < mobileBreakpoint) { // 按视口比例缩放,也可以改成固定差值(比如视口<768时用12px,<480时用10px) fontSize = baseFontSize * (viewportWidth / mobileBreakpoint); fontSize = Math.max(fontSize, minFontSize); } // 更新Canvas字体样式,然后重新绘制图例 ctx.font = `${fontSize}px sans-serif`; renderLegend(); // 你的图例绘制函数 }
2. 用CSS相对单位配合Canvas读取
如果你的图表有对应的DOM容器,可以先通过CSS的vw单位定义字体大小,再让Canvas读取计算后的值,这样能和页面其他元素的响应式逻辑保持一致:
/* 给图例容器设置相对字体大小 */ .chart-legend-wrapper { font-size: 1.7vw; min-font-size: 10px; }
// 获取计算后的字体大小 const legendWrapper = document.querySelector('.chart-legend-wrapper'); const computedFontSize = parseFloat(window.getComputedStyle(legendWrapper).fontSize); // 应用到Canvas ctx.font = `${computedFontSize}px sans-serif`; renderLegend();
3. 自动换行+动态缩容适配长文本
如果图例文本本身较长,除了缩小字体,还可以结合文本宽度检测实现自动换行,或者调整图例布局(比如从横向排列改为纵向):
function renderLegend() { const legendItems = ['月度销售总额', '季度目标完成率', '年度同比增长率']; const maxAvailableWidth = ctx.canvas.width - 40; // 图例区域可用宽度 let currentY = 20; // 图例起始Y坐标 legendItems.forEach(item => { let fontSize = 14; ctx.font = `${fontSize}px sans-serif`; let textWidth = ctx.measureText(item).width; // 如果文本超出可用宽度,逐步缩小字体直到合适 while (textWidth > maxAvailableWidth && fontSize > 10) { fontSize--; ctx.font = `${fontSize}px sans-serif`; textWidth = ctx.measureText(item).width; } // 绘制文本 ctx.fillText(item, 20, currentY); currentY += fontSize + 8; // 控制图例项之间的间距 }); }
4. 整体缩放图例绘制区域
如果图例的布局比较复杂(比如带图标、多列排列),直接缩放整个绘制区域会更高效:
function renderLegend() { const viewportWidth = window.innerWidth; const scaleRatio = viewportWidth < 768 ? viewportWidth / 768 : 1; // 缩放比例 const legendStartX = 20; const legendStartY = 20; // 保存当前画布状态,避免影响其他绘制内容 ctx.save(); // 平移到图例起始位置,再执行缩放 ctx.translate(legendStartX, legendStartY); ctx.scale(scaleRatio, scaleRatio); // 这里按桌面端的尺寸绘制图例即可,缩放会自动适配移动端 ctx.font = '14px sans-serif'; ctx.fillText('图例1', 0, 0); ctx.fillText('图例2', 0, 20); // 绘制图例图标... // 恢复画布原始状态 ctx.restore(); }
你可以根据自己的图表结构和需求选择最合适的方案,要是有更具体的图例布局细节,也能调整这些代码的逻辑~
内容的提问来源于stack exchange,提问作者KMG
相关产品推荐
相关产品推荐

