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

Canvas旋转轮设置lineWidth后边缘截断及文本堆叠旋转问题

Canvas旋转轮问题修复方案

问题1:设置lineWidth后边缘被截断

原因

Canvas绘制描边时,线条宽度的一半会向外延伸出路径范围。你的代码中用rad作为扇形绘制半径,画布尺寸为2*rad,导致描边的外侧部分超出画布边界被截断。

修复方案

有两种常用解决方式:

方式1:缩小绘制半径,预留描边空间

将扇形的绘制半径从rad改为rad - lineWidth/2,让描边外侧刚好贴合画布边缘:

const drawSector = (sector, i) => {
  const ang = arc * i;
  const lineWidth = 10;
  const drawRad = rad - lineWidth / 2; // 调整后的绘制半径
  ctx.save();
  // 绘制扇形部分
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = "#ECBA3F";
  ctx.beginPath();
  ctx.fillStyle = sector.color;
  ctx.moveTo(rad, rad);
  ctx.arc(rad, rad, drawRad, ang, ang + arc); // 使用调整后的半径
  ctx.lineTo(rad, rad);
  ctx.fill();
  ctx.stroke();
  // 文本部分
  ctx.translate(rad, rad);
  ctx.rotate(ang + arc / 2);
  ctx.textAlign = "right";
  ctx.fillStyle = "#000";
  ctx.font = "bold 10px sans-serif";
  ctx.fillText(sector.label, drawRad - 10, 10); // 文本位置对应调整
  ctx.restore();
};

方式2:扩大画布尺寸,容纳描边

将画布宽高设置为2*(rad + lineWidth/2),同时把绘制中心调整为画布中点,确保描边完全在画布内:

// 调整画布尺寸
const lineWidth = 10;
const canvasSize = 2 * (rad + lineWidth / 2);
canvas.width = canvasSize;
canvas.height = canvasSize;
const centerX = canvasSize / 2;
const centerY = canvasSize / 2;

const drawSector = (sector, i) => {
  const ang = arc * i;
  ctx.save();
  // 绘制扇形部分
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = "#ECBA3F";
  ctx.beginPath();
  ctx.fillStyle = sector.color;
  ctx.moveTo(centerX, centerY);
  ctx.arc(centerX, centerY, rad, ang, ang + arc);
  ctx.lineTo(centerX, centerY);
  ctx.fill();
  ctx.stroke();
  // 文本部分
  ctx.translate(centerX, centerY);
  ctx.rotate(ang + arc / 2);
  ctx.textAlign = "right";
  ctx.fillStyle = "#000";
  ctx.font = "bold 10px sans-serif";
  ctx.fillText(sector.label, rad - 10, 10);
  ctx.restore();
};

问题2:实现扇形内文本堆叠旋转

实现思路

把文本拆分为单个字符(或按语义拆分的词语),通过旋转画布让文本垂直排列,再逐行绘制每个单元,形成堆叠效果。

修改后的代码示例

const drawSector = (sector, i) => {
  const ang = arc * i;
  const lineWidth = 10;
  const drawRad = rad - lineWidth / 2;
  ctx.save();
  // 绘制扇形部分(同问题1修复后的代码)
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = "#ECBA3F";
  ctx.beginPath();
  ctx.fillStyle = sector.color;
  ctx.moveTo(rad, rad);
  ctx.arc(rad, rad, drawRad, ang, ang + arc);
  ctx.lineTo(rad, rad);
  ctx.fill();
  ctx.stroke();
  // 堆叠旋转文本部分
  ctx.translate(rad, rad);
  ctx.rotate(ang + arc / 2);
  // 额外旋转90度,使文本垂直排列
  ctx.rotate(-Math.PI / 2);
  ctx.textAlign = "center";
  ctx.fillStyle = "#000";
  ctx.font = "bold 10px sans-serif";
  const textLines = sector.label.split(''); // 按单个字符拆分,按词语拆分可改为split(' ')
  const lineSpacing = 15; // 行间距,可根据字体大小调整
  // 逐行绘制文本
  textLines.forEach((line, idx) => {
    ctx.fillText(line, drawRad - 20, idx * lineSpacing);
  });
  ctx.restore();
};

说明

  • 文本拆分:如果标签是词语组合,用split(' ')按空格拆分更符合语义。
  • 排版调整:lineSpacing控制行间距,drawRad - 20控制文本距扇形边缘的距离,可按需修改。

内容的提问来源于stack exchange,提问作者aachukay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:25:58