Skip to content

Commit 33e11de

Browse files
committed
feat: refactor logo scramble animation to support multi-line text elements with responsive layout adjustments
1 parent 2a7b4f7 commit 33e11de

3 files changed

Lines changed: 87 additions & 26 deletions

File tree

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
<!-- 英雄区域 -->
3333
<section class="hero">
3434
<div class="hero-content">
35-
<h1 class="logo-text">字节交汇皆有引力</h1>
35+
<h1 class="logo-text"><span class="logo-line">字节交汇</span><span class="logo-line">皆有引力</span></h1>
3636
<p class="logo-english">ByteGravity</p>
3737
<p class="tagline">
3838
我们运营 toB 与 toC 两大差异化广告网络<br>让品牌与媒体的每一个字节都拥有强大的传播引力

main.js

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,42 +26,91 @@ function scrambleLogoText() {
2626
const el = document.querySelector(".logo-text");
2727
if (!el) return;
2828

29-
const target = el.textContent;
30-
// 字符池全部使用全角字符(与汉字同宽 1em),避免闪变时标题总宽度抖动
29+
const lines = el.querySelectorAll(".logo-line");
3130
const chars =
3231
"字节引力天津科技有限公司*广告联盟网络01<>#*+=/\|ABCDEFGHKMNRSTWXYZ";
3332
const frameInterval = 40; // 每帧毫秒数
3433
const lockStagger = 233; // 相邻字符锁定时刻间隔(毫秒),总时长约 1.6s
35-
const frames = [];
3634

37-
for (let i = 0; i < target.length; i++) {
38-
// 标点不闪变,直接保持
39-
const lockAt = target[i].match(/[,.!?]/) ? 0 : i * lockStagger;
40-
frames.push({ char: target[i], lockAt });
41-
}
35+
if (lines.length > 0) {
36+
// 存在 .logo-line 分行元素时,针对每个 span 分别计算并更新,保留 HTML 结构
37+
const lineData = [];
38+
let globalIndex = 0;
39+
40+
lines.forEach((lineEl) => {
41+
const target = lineEl.textContent;
42+
const frames = [];
43+
for (let i = 0; i < target.length; i++) {
44+
const lockAt = target[i].match(/[,.!?]/) ? 0 : globalIndex * lockStagger;
45+
frames.push({ char: target[i], lockAt });
46+
globalIndex++;
47+
}
48+
lineData.push({ el: lineEl, target, frames });
49+
});
4250

43-
const start = performance.now();
44-
const timer = setInterval(() => {
45-
const elapsed = performance.now() - start;
46-
let done = true;
47-
let output = "";
51+
const start = performance.now();
52+
const timer = setInterval(() => {
53+
const elapsed = performance.now() - start;
54+
let allDone = true;
55+
56+
for (const line of lineData) {
57+
let lineDone = true;
58+
let output = "";
59+
60+
for (const f of line.frames) {
61+
if (elapsed >= f.lockAt) {
62+
output += f.char;
63+
} else {
64+
lineDone = false;
65+
output += chars[Math.floor(Math.random() * chars.length)];
66+
}
67+
}
4868

49-
for (const f of frames) {
50-
if (elapsed >= f.lockAt) {
51-
output += f.char;
52-
} else {
53-
done = false;
54-
output += chars[Math.floor(Math.random() * chars.length)];
69+
line.el.textContent = output;
70+
if (!lineDone) {
71+
allDone = false;
72+
}
73+
}
74+
75+
if (allDone) {
76+
clearInterval(timer);
77+
lineData.forEach((line) => {
78+
line.el.textContent = line.target;
79+
});
5580
}
81+
}, frameInterval);
82+
} else {
83+
// 降级处理:无 .logo-line 结构时直接处理整个 el
84+
const target = el.textContent;
85+
const frames = [];
86+
for (let i = 0; i < target.length; i++) {
87+
const lockAt = target[i].match(/[,.!?]/) ? 0 : i * lockStagger;
88+
frames.push({ char: target[i], lockAt });
5689
}
5790

58-
el.textContent = output;
91+
const start = performance.now();
92+
const timer = setInterval(() => {
93+
const elapsed = performance.now() - start;
94+
let done = true;
95+
let output = "";
96+
97+
for (const f of frames) {
98+
if (elapsed >= f.lockAt) {
99+
output += f.char;
100+
} else {
101+
done = false;
102+
output += chars[Math.floor(Math.random() * chars.length)];
103+
}
104+
}
59105

60-
if (done) {
61-
clearInterval(timer);
62-
el.textContent = target;
63-
}
64-
}, frameInterval);
106+
el.textContent = output;
107+
108+
if (done) {
109+
clearInterval(timer);
110+
el.textContent = target;
111+
}
112+
}, frameInterval);
113+
}
65114
}
66115

67116
// 滚动动画 - IntersectionObserver

styles.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ body {
304304
animation: glow 2s ease-in-out infinite alternate;
305305
}
306306

307+
.logo-text .logo-line:first-child {
308+
margin-right: 0.4em;
309+
}
310+
307311
@keyframes glow {
308312
from {
309313
filter: drop-shadow(0 0 20px rgba(99, 102, 241, 0.3));
@@ -788,6 +792,14 @@ footer {
788792
letter-spacing: 0.05em;
789793
}
790794

795+
.logo-text .logo-line {
796+
display: block;
797+
}
798+
799+
.logo-text .logo-line:first-child {
800+
margin-right: 0;
801+
}
802+
791803
.logo-english {
792804
letter-spacing: 0.15em;
793805
font-size: 1rem;

0 commit comments

Comments
 (0)