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

Canvas卡拉OK文字渲染效果调用后延迟3-4秒,如何实现即时运行?

解决Canvas卡拉OK文字动画延迟启动问题

你的动画延迟3-4秒才生效,核心原因是裁剪区域的起始位置和文字实际位置不匹配:代码里文字是居中绘制的(x = canvas.width/2),但裁剪区域的起始X坐标clearX固定为8,导致w需要增长到280左右(画布中心到8的距离),裁剪区域才会覆盖到文字,这段时间里动画看不到任何变化,看起来就像延迟启动。

修改后的代码

const canvas = document.querySelector("#draw-pad");
const ctx = canvas.getContext("2d");
// 保存动画ID,防止重复调用时多个动画冲突
let animationId = null;

function runTextAnimation(text) {
  // 先取消之前的动画
  if (animationId) {
    cancelAnimationFrame(animationId);
  }

  const txt = text;
  // 先设置字体,才能计算文字实际宽度
  ctx.font = 'bold 17px Arial';
  const textWidth = ctx.measureText(txt).width;
  
  // 文字居中参数
  const x = canvas.width / 2;
  const y = canvas.height / 2;
  // 裁剪区域从文字左侧开始,而非固定的8
  const clearX = x - textWidth / 2;
  const clearY = 5;
  const clearH = 40;
  let w = 0;

  ctx.lineWidth = 2;
  ctx.strokeStyle = 'black';

  function runText() {
    // 清空整个画布,避免残留绘制内容
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // 绘制底层浅蓝色文字
    ctx.fillStyle = 'lightblue';
    ctx.strokeText(txt, x, y);
    ctx.fillText(txt, x, y);

    // 裁剪区域内绘制红色覆盖层
    ctx.save();
    ctx.beginPath();
    ctx.rect(clearX, clearY, w, clearH);
    ctx.clip();
    ctx.fillStyle = 'red';
    ctx.strokeStyle = 'white';
    ctx.strokeText(txt, x, y);
    ctx.fillText(txt, x, y);
    ctx.restore();

    // 动画进度控制:覆盖完整个文字后重置
    if (w >= textWidth) {
      w = 0;
    } else {
      w += 1.92;
    }

    animationId = requestAnimationFrame(runText);
  }
  // 立即执行第一帧动画
  runText();
}

runTextAnimation("chắc không phải một người như anh");

关键修改点

  1. 匹配裁剪区域与文字位置:通过measureText计算文字实际宽度,让裁剪区域从文字左侧开始,动画启动后立即能看到红色覆盖效果。
  2. 管理动画生命周期:新增animationId,重复调用函数时会先取消之前的动画,避免多个动画叠加导致的混乱。
  3. 简化绘制逻辑:每次帧绘制前清空整个画布,移除原代码中冗余的clearRect调用,让动画逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:13:11