如何实现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或动画帧回调,把坐标更新逻辑套进去:
- 找到设置渐变起点的函数(比如
setGradientStart(x,y)) - 用TonyBrush的动画定时器替换
requestAnimationFrame - 按阶段计算每帧的坐标,调用API更新
内容的提问来源于stack exchange,提问作者Luuke
相关产品推荐
相关产品推荐

