Skip to content

Commit 3099fd7

Browse files
committed
feat: optimize slogan animation with smooth color interpolation
Implemented true color interpolation for buttery smooth gradient animation: - Added hexToRgb, rgbToHex, and interpolateColor functions for mathematical color blending - Increased frame rate from 24 to 60 FPS for ultra-smooth motion - Changed easing from cubic to sine wave for more natural transitions - Dynamically generate gradients per frame instead of using pre-defined set - Eliminates staggered/jumping effect in the slogan text animation The animation now uses real-time color interpolation between adjacent colors in the sequence, creating seamless transitions without visible steps.
1 parent 0410617 commit 3099fd7

File tree

1 file changed

+90
-14
lines changed

1 file changed

+90
-14
lines changed

src/core/logo.ts

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,103 @@ function createBlueGradient(text: string): string {
2525
}
2626

2727
/**
28-
* 显示渐变动画效果(优化版 - 更丝滑的动画)
28+
* 将十六进制颜色转换为RGB
29+
*/
30+
function hexToRgb(hex: string): [number, number, number] {
31+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
32+
return result
33+
? [parseInt(result[1]!, 16), parseInt(result[2]!, 16), parseInt(result[3]!, 16)]
34+
: [0, 0, 0];
35+
}
36+
37+
/**
38+
* 将RGB转换为十六进制颜色
39+
*/
40+
function rgbToHex(r: number, g: number, b: number): string {
41+
return '#' + [r, g, b].map(x => {
42+
const hex = Math.round(x).toString(16);
43+
return hex.length === 1 ? '0' + hex : hex;
44+
}).join('');
45+
}
46+
47+
/**
48+
* 在两个颜色之间进行线性插值
49+
*/
50+
function interpolateColor(color1: string, color2: string, factor: number): string {
51+
const [r1, g1, b1] = hexToRgb(color1);
52+
const [r2, g2, b2] = hexToRgb(color2);
53+
54+
const r = r1 + (r2 - r1) * factor;
55+
const g = g1 + (g2 - g1) * factor;
56+
const b = b1 + (b2 - b1) * factor;
57+
58+
return rgbToHex(r, g, b);
59+
}
60+
61+
/**
62+
* 缓动函数 - 平滑的进出效果
63+
*/
64+
function easeInOutSine(t: number): number {
65+
return -(Math.cos(Math.PI * t) - 1) / 2;
66+
}
67+
68+
/**
69+
* 显示渐变动画效果(优化版 - 真正丝滑的动画)
2970
*/
3071
async function animateGradient(text: string, duration: number = 1200): Promise<void> {
31-
const frames = 24; // 增加帧数使动画更流畅
72+
const frames = 60; // 60帧实现真正的流畅动画
3273
const frameDelay = duration / frames;
3374

34-
// 预创建所有渐变对象
35-
const gradients = [
36-
gradient('#1e3a8a', '#2563eb', '#3b82f6'),
37-
gradient('#2563eb', '#3b82f6', '#0ea5e9'),
38-
gradient('#3b82f6', '#0ea5e9', '#06b6d4'),
39-
gradient('#0ea5e9', '#06b6d4', '#14b8a6'),
40-
gradient('#06b6d4', '#14b8a6', '#0ea5e9'),
41-
gradient('#14b8a6', '#0ea5e9', '#3b82f6'),
42-
gradient('#0ea5e9', '#3b82f6', '#2563eb'),
43-
gradient('#3b82f6', '#2563eb', '#1e3a8a'),
75+
// 定义颜色序列 - 形成完整的蓝色系循环
76+
const colorSequence = [
77+
'#1e3a8a', // 深蓝
78+
'#2563eb', // 蓝
79+
'#3b82f6', // 亮蓝
80+
'#0ea5e9', // 天蓝
81+
'#06b6d4', // 青色
82+
'#14b8a6', // 青绿
83+
'#06b6d4', // 青色
84+
'#0ea5e9', // 天蓝
85+
'#3b82f6', // 亮蓝
86+
'#2563eb', // 蓝
87+
'#1e3a8a', // 深蓝
4488
];
4589

4690
for (let i = 0; i < frames; i++) {
47-
const gradientIndex = Math.floor((i / frames) * gradients.length);
48-
const frameGradient = gradients[gradientIndex]!;
91+
// 使用平滑的正弦缓动
92+
const progress = easeInOutSine(i / frames);
93+
94+
// 计算在颜色序列中的位置
95+
const position = progress * (colorSequence.length - 1);
96+
const index1 = Math.floor(position);
97+
const index2 = Math.min(index1 + 1, colorSequence.length - 1);
98+
const localProgress = position - index1;
99+
100+
// 在相邻颜色间插值,生成三个平滑过渡的颜色
101+
const color1 = interpolateColor(
102+
colorSequence[index1]!,
103+
colorSequence[index2]!,
104+
localProgress
105+
);
106+
107+
const nextIndex1 = Math.min(index2, colorSequence.length - 1);
108+
const nextIndex2 = Math.min(nextIndex1 + 1, colorSequence.length - 1);
109+
const color2 = interpolateColor(
110+
colorSequence[nextIndex1]!,
111+
colorSequence[nextIndex2]!,
112+
localProgress
113+
);
114+
115+
const nextIndex3 = Math.min(nextIndex2, colorSequence.length - 1);
116+
const nextIndex4 = Math.min(nextIndex3 + 1, colorSequence.length - 1);
117+
const color3 = interpolateColor(
118+
colorSequence[nextIndex3]!,
119+
colorSequence[nextIndex4]!,
120+
localProgress
121+
);
122+
123+
// 为当前帧创建渐变
124+
const frameGradient = gradient(color1, color2, color3);
49125

50126
// 清除当前行并显示新帧
51127
process.stdout.write('\r' + frameGradient(text));

0 commit comments

Comments
 (0)