You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:11:24