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

如何实现LinearGradientBrush的顺时针往返旋转动画?

实现渐变起点的两段式往返动画(P1→P2→顺时针返回P1)

方案一:JavaScript + Canvas 精确控制(推荐)

如果需要精准控制圆弧路径,用JS+Canvas可以直接计算每帧的渐变起点坐标,完美匹配需求:

<canvas id="gradientCanvas" width="200" height="200"></canvas>
const canvas = document.getElementById('gradientCanvas');
const ctx = canvas.getContext('2d');

// 自定义坐标(根据你的图修改)
const P1 = { x: 50, y: 50 };    // 初始起点
const P2 = { x: 150, y: 50 };   // 固定终点
const center = { x: 100, y: 100 }; // 顺时针旋转的圆心(自行调整)

// 计算圆弧参数
const radius = Math.sqrt(Math.pow(P2.x - center.x, 2) + Math.pow(P2.y - center.y, 2));
const angleP2 = Math.atan2(P2.y - center.y, P2.x - center.x);
const angleP1 = Math.atan2(P1.y - center.y, P1.x - center.x);
let totalAngle = angleP2 - angleP1;
if (totalAngle < 0) totalAngle += 2 * Math.PI;

// 动画时长(毫秒)
const moveDuration = 2000;   // P1到P2的时间
const rotateDuration = 2000; // 顺时针返回的时间

let startTime = null;
let step = 1; // 1=移动阶段,2=旋转阶段

function updateFrame(timestamp) {
  if (!startTime) startTime = timestamp;
  const elapsed = timestamp - startTime;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  let currentStart;

  if (step === 1) {
    // 线性移动:从P1到P2
    const progress = Math.min(elapsed / moveDuration, 1);
    currentStart = {
      x: P1.x + (P2.x - P1.x) * progress,
      y: P1.y + (P2.y - P1.y) * progress
    };

    if (progress >= 1) {
      step = 2;
      startTime = timestamp; // 重置计时
    }
  } else if (step === 2) {
    // 顺时针圆弧返回:从P2到P1
    const progress = Math.min(elapsed / rotateDuration, 1);
    const currentAngle = angleP2 - totalAngle * progress;
    currentStart = {
      x: center.x + radius * Math.cos(currentAngle),
      y: center.y + radius * Math.sin(currentAngle)
    };

    if (progress >= 1) return; // 动画结束,停止循环
  } else {
    currentStart = P1;
  }

  // 绘制渐变
  const gradient = ctx.createLinearGradient(currentStart.x, currentStart.y, P2.x, P2.y);
  gradient.addColorStop(0, '#ff0000');
  gradient.addColorStop(1, '#0000ff');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  requestAnimationFrame(updateFrame);
}

// 启动动画
requestAnimationFrame(updateFrame);

方案二:CSS 关键帧(适合简单场景)

如果不需要精准圆弧,或者用DOM元素的背景渐变,可以用CSS变量+关键帧模拟,缺点是圆弧路径需要手动拆分关键帧:

:root {
  --start-x: 0px;
  --start-y: 0px;
}

.gradient-box {
  width: 200px;
  height: 200px;
  background: linear-gradient(from var(--start-x) var(--start-y), red, blue);
  animation: grad-move-rotate 4s forwards;
}

@keyframes grad-move-rotate {
  0% {
    --start-x: 0px;
    --start-y: 0px;
  }
  50% {
    --start-x: 100px;
    --start-y: 0px;
  }
  /* 手动拆分圆弧路径的中间点,按需调整坐标 */
  60% {
    --start-x: 120px;
    --start-y: 20px;
  }
  70% {
    --start-x: 100px;
    --start-y: 40px;
  }
  80% {
    --start-x: 80px;
    --start-y: 20px;
  }
  100% {
    --start-x: 0px;
    --start-y: 0px;
  }
}

适配TonyBrush的提示

如果是在TonyBrush中实现,需要找到工具内置的渐变起点控制API或动画帧回调,把坐标更新逻辑套进去:

  1. 找到设置渐变起点的函数(比如setGradientStart(x,y))
  2. 用TonyBrush的动画定时器替换requestAnimationFrame
  3. 按阶段计算每帧的坐标,调用API更新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:06:46