Skip to content

Commit 6dee9f9

Browse files
taeaclaude
andcommitted
Adjust train animation to sync with heartbeat interval
- Change train from continuous loop to 8s interval gatagata animation - Add new train-heartbeat animation with train-running style movement - Change all heartbeat animations from 10s to 8s interval 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 9ac839c commit 6dee9f9

3 files changed

Lines changed: 72 additions & 16 deletions

File tree

javascripts/hero-animation.js

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,9 @@ document.addEventListener('DOMContentLoaded', () => {
188188
setTimeout(() => {
189189
// Train has a special slide-in animation (no bounce)
190190
if (illust.hasAttribute('data-hero-train')) {
191-
// Train appears later and starts running immediately after slide-in
191+
// Train appears later with slide-in animation
192192
setTimeout(() => {
193193
illust.classList.add('animate-train-slide-in');
194-
// Start running animation right after slide-in completes (600ms)
195-
setTimeout(() => {
196-
illust.classList.remove('animate-train-slide-in');
197-
illust.classList.add('animate-train-running');
198-
}, 600);
199194
}, trainExtraDelay);
200195
} else {
201196
illust.classList.add('animate-pop-in');
@@ -235,14 +230,16 @@ document.addEventListener('DOMContentLoaded', () => {
235230
if (layers.illustMain) {
236231
const illusts = layers.illustMain.querySelectorAll('img');
237232
illusts.forEach(illust => {
238-
// Train already has running animation, skip it
233+
// Remove initial animation classes first to avoid conflict
234+
illust.classList.remove('animate-pop-in');
235+
illust.classList.remove('animate-train-slide-in');
236+
// Train uses its own heartbeat animation with gatagata movement
239237
if (illust.hasAttribute('data-hero-train')) {
240-
return;
238+
illust.classList.add('animate-train-heartbeat');
239+
} else {
240+
// Use illust-specific heartbeat that preserves opacity
241+
illust.classList.add('animate-heartbeat-illust');
241242
}
242-
// Remove pop-in animation class first to avoid conflict
243-
illust.classList.remove('animate-pop-in');
244-
// Use illust-specific heartbeat that preserves opacity
245-
illust.classList.add('animate-heartbeat-illust');
246243
});
247244
}
248245
}, heartbeatStartDelay);

stylesheets/compiled.css

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,7 +3179,7 @@ body:is(.dark *){
31793179
}
31803180

31813181
.animate-heartbeat{
3182-
animation: heartbeat 10s ease-in-out infinite;
3182+
animation: heartbeat 8s ease-in-out infinite;
31833183
}
31843184

31853185
@keyframes heartbeat-illust{
@@ -3215,7 +3215,7 @@ body:is(.dark *){
32153215
}
32163216

32173217
.animate-heartbeat-illust{
3218-
animation: heartbeat-illust 10s ease-in-out infinite;
3218+
animation: heartbeat-illust 8s ease-in-out infinite;
32193219
}
32203220

32213221
@keyframes pop-in{
@@ -3263,6 +3263,52 @@ body:is(.dark *){
32633263
animation: scroll-left 60s linear infinite;
32643264
}
32653265

3266+
@keyframes train-heartbeat{
3267+
0%, 100%{
3268+
opacity: 1;
3269+
transform: translateX(0) rotate(var(--tw-rotate, 0deg));
3270+
}
3271+
3272+
0.5%{
3273+
opacity: 1;
3274+
transform: translateX(2px) rotate(calc(var(--tw-rotate, 0deg) + 0.4deg));
3275+
}
3276+
3277+
1%{
3278+
opacity: 1;
3279+
transform: translateX(-1.5px) rotate(calc(var(--tw-rotate, 0deg) - 0.3deg));
3280+
}
3281+
3282+
1.5%{
3283+
opacity: 1;
3284+
transform: translateX(2px) rotate(calc(var(--tw-rotate, 0deg) + 0.3deg));
3285+
}
3286+
3287+
2%{
3288+
opacity: 1;
3289+
transform: translateX(-1px) rotate(calc(var(--tw-rotate, 0deg) - 0.2deg));
3290+
}
3291+
3292+
2.5%{
3293+
opacity: 1;
3294+
transform: translateX(1.5px) rotate(calc(var(--tw-rotate, 0deg) + 0.2deg));
3295+
}
3296+
3297+
3%{
3298+
opacity: 1;
3299+
transform: translateX(-0.5px) rotate(calc(var(--tw-rotate, 0deg) - 0.1deg));
3300+
}
3301+
3302+
3.5%{
3303+
opacity: 1;
3304+
transform: translateX(0) rotate(var(--tw-rotate, 0deg));
3305+
}
3306+
}
3307+
3308+
.animate-train-heartbeat{
3309+
animation: train-heartbeat 8s ease-in-out infinite;
3310+
}
3311+
32663312
@keyframes train-running{
32673313
0%, 100%{
32683314
opacity: 1;

tailwind.config.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module.exports = {
4040
'animate-heartbeat-illust',
4141
'animate-train-slide-in',
4242
'animate-train-running',
43+
'animate-train-heartbeat',
4344
],
4445
theme: {
4546
container: {
@@ -124,6 +125,17 @@ module.exports = {
124125
'50%': { opacity: '1', transform: 'translateX(-1px) rotate(calc(var(--tw-rotate, 0deg) - 0.2deg))' },
125126
'75%': { opacity: '1', transform: 'translateX(1.5px) rotate(calc(var(--tw-rotate, 0deg) + 0.2deg))' },
126127
},
128+
// Train heartbeat animation (gatagata movement at 10s intervals)
129+
'train-heartbeat': {
130+
'0%, 100%': { opacity: '1', transform: 'translateX(0) rotate(var(--tw-rotate, 0deg))' },
131+
'0.5%': { opacity: '1', transform: 'translateX(2px) rotate(calc(var(--tw-rotate, 0deg) + 0.4deg))' },
132+
'1%': { opacity: '1', transform: 'translateX(-1.5px) rotate(calc(var(--tw-rotate, 0deg) - 0.3deg))' },
133+
'1.5%': { opacity: '1', transform: 'translateX(2px) rotate(calc(var(--tw-rotate, 0deg) + 0.3deg))' },
134+
'2%': { opacity: '1', transform: 'translateX(-1px) rotate(calc(var(--tw-rotate, 0deg) - 0.2deg))' },
135+
'2.5%': { opacity: '1', transform: 'translateX(1.5px) rotate(calc(var(--tw-rotate, 0deg) + 0.2deg))' },
136+
'3%': { opacity: '1', transform: 'translateX(-0.5px) rotate(calc(var(--tw-rotate, 0deg) - 0.1deg))' },
137+
'3.5%': { opacity: '1', transform: 'translateX(0) rotate(var(--tw-rotate, 0deg))' },
138+
},
127139
'wave-scroll': {
128140
'0%': { transform: 'translateX(0)' },
129141
'100%': { transform: 'translateX(-50%)' },
@@ -137,10 +149,11 @@ module.exports = {
137149
'pop-in': 'pop-in 0.4s ease-out forwards',
138150
'gem-zoom-in': 'gem-zoom-in 0.6s ease-out forwards',
139151
'fade-slide-in': 'fade-slide-in 0.6s ease-out forwards',
140-
'heartbeat': 'heartbeat 10s ease-in-out infinite',
141-
'heartbeat-illust': 'heartbeat-illust 10s ease-in-out infinite',
152+
'heartbeat': 'heartbeat 8s ease-in-out infinite',
153+
'heartbeat-illust': 'heartbeat-illust 8s ease-in-out infinite',
142154
'train-slide-in': 'train-slide-in 0.6s ease-out forwards',
143155
'train-running': 'train-running 0.4s ease-in-out infinite',
156+
'train-heartbeat': 'train-heartbeat 8s ease-in-out infinite',
144157
'wave-scroll': 'wave-scroll 2s linear infinite',
145158
},
146159
colors: {

0 commit comments

Comments
 (0)