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

Canvas抽奖转盘如何实现扇形区域内文本换行适配

Canvas抽奖转盘扇形文本换行实现方案

问题根源

<br>是HTML标签,\r\n是纯文本换行符,二者都无法被Canvas 2D的fillText()API识别。该API默认只会把传入内容当做单行字符串绘制,不会自动处理换行,所以之前的写法不会生效。

实现步骤

核心逻辑是手动拆分长文本为多行,逐行调用绘制API,不需要改动原有转盘的旋转、动画逻辑,只需要修改文本绘制部分和少量样式即可。

  • 提前定义文本显示规则:包括扇形内文本最大允许宽度、行高、字体大小、边距
  • 按文本宽度自动拆分长文本为多个短行,保证每行宽度不超过扇形可容纳范围
  • 计算多行文本的整体偏移量,保证文本在扇形区域内居中显示
  • 逐行绘制拆分后的文本片段
  • 调整中间SPIN按钮的样式,支持DOM文本换行

改造后的核心代码

1. 替换原有的drawSector函数

// 文本显示配置,可根据转盘实际尺寸调整参数
const textConfig = {
    maxWidth: rad * 0.6, // 文本最大宽度,占半径60%,避免溢出到相邻扇形
    lineHeight: 40,
    fontSize: 30,
    paddingRight: 20, // 文本距离转盘外边缘的距离
    font: "bold 30px sans-serif"
};

const drawSector = (sector, i) => {
    const ang = arc * i;
    ctx.save();
    // 绘制扇形背景
    ctx.beginPath();
    ctx.fillStyle = sector.color;
    ctx.moveTo(rad, rad);
    ctx.arc(rad, rad, rad, ang, ang + arc);
    ctx.lineTo(rad, rad);
    ctx.fill();
    // 绘制多行文本
    ctx.translate(rad, rad);
    ctx.rotate(ang + arc / 2);
    ctx.textAlign = "right";
    ctx.textBaseline = "middle";
    ctx.fillStyle = "#fff";
    ctx.font = textConfig.font;

    // 英文按空格拆词,中文请替换为下方的中文拆词逻辑
    const words = sector.label.split(' ');
    const lines = [];
    let currentLine = words[0];
    for (let n = 1; n < words.length; n++) {
        const testLine = `${currentLine} ${words[n]}`;
        if (ctx.measureText(testLine).width > textConfig.maxWidth) {
            lines.push(currentLine);
            currentLine = words[n];
        } else {
            currentLine = testLine;
        }
    }
    lines.push(currentLine);

    // 计算垂直居中的起始坐标
    const startY = -(lines.length - 1) * textConfig.lineHeight / 2;
    // 逐行绘制
    lines.forEach((line, idx) => {
        ctx.fillText(line, rad - textConfig.paddingRight, startY + idx * textConfig.lineHeight);
    });
    ctx.restore();
};

中文场景拆词逻辑替换

如果转盘用中文文本,把上面代码里拆词的部分替换成逐字符判断即可:

const chars = sector.label.split('');
const lines = [];
let currentLine = chars[0];
for (let n = 1; n < chars.length; n++) {
    const testLine = currentLine + chars[n];
    if (ctx.measureText(testLine).width > textConfig.maxWidth) {
        lines.push(currentLine);
        currentLine = chars[n];
    } else {
        currentLine = testLine;
    }
}
lines.push(currentLine);

2. 调整中间SPIN按钮的样式,支持长文本换行

修改原有#spin的CSS样式,把原来的font: 1.5rem/0 sans-serif;替换,新增换行相关属性:

#spin {
    /* 保留原有其他样式,修改和新增以下属性 */
    font: 1.5rem/1.2 sans-serif;
    white-space: normal;
    text-align: center;
    padding: 10px;
    box-sizing: border-box;
}

参数调整说明

如果出现文本溢出扇形、或者显示太挤的情况,直接调整textConfig里的三个参数即可:

  • 调小maxWidth可以让文本更早换行,避免溢出到相邻扇形
  • 调小fontSize和lineHeight可以容纳更多行文本
  • 调整paddingRight可以控制文本离转盘外边缘的距离

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 10:12:26