diff --git a/TUICallKit-Vue3/pages/training/metronome.vue b/TUICallKit-Vue3/pages/training/metronome.vue index c826a975..f2256a17 100644 --- a/TUICallKit-Vue3/pages/training/metronome.vue +++ b/TUICallKit-Vue3/pages/training/metronome.vue @@ -28,21 +28,13 @@ - + - - - - - + @@ -414,7 +406,7 @@ $radius-btn: 20rpx; .walker { position: relative; width: 100%; - height: 220rpx; + height: 240rpx; display: flex; justify-content: center; align-items: flex-end; @@ -436,108 +428,86 @@ $radius-btn: 20rpx; } /* ============================================================ - * 拟真脚印(SVG 矢量,单笔成型) + * 跑步小人(静态 PNG + CSS 律动) * ============================================================ */ -.foot { +.runner-wrap { position: absolute; - bottom: 22rpx; - width: 96rpx; - height: 144rpx; - - .footprint { - display: block; - width: 100%; - height: 100%; - transform-origin: bottom center; - } - - .shadow { - position: absolute; - bottom: -6rpx; - left: 50%; - transform: translateX(-50%); - width: 70rpx; - height: 8rpx; - background: radial-gradient( - ellipse at center, - rgba(0, 0, 0, 0.45), - transparent 70% - ); - border-radius: 50%; - } + bottom: 18rpx; + left: 50%; + transform: translateX(-50%); + width: 200rpx; + height: 200rpx; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-end; } -.foot-left { - left: calc(50% - 124rpx); -} -.foot-left .footprint { - transform: scaleX(-1); -} -.foot-right { - left: calc(50% + 24rpx); +.runner { + width: 100%; + height: 100%; + transform-origin: bottom center; + /* 默认状态保持微妙的呼吸感,不至于完全静止 */ + transition: filter 0.3s; } -/* 跟节拍同步:1 拍 1 步,左右各占半周期 */ -.walker.playing { - .foot-left .footprint { - animation: foot-step-left var(--step-duration, 750ms) ease-in-out infinite; - } - .foot-right .footprint { - animation: foot-step-right var(--step-duration, 750ms) ease-in-out infinite; - animation-delay: calc(var(--step-duration, 750ms) * -0.5); - } - .foot-left .shadow { - animation: shadow-pulse var(--step-duration, 750ms) ease-in-out infinite; - } - .foot-right .shadow { - animation: shadow-pulse var(--step-duration, 750ms) ease-in-out infinite; - animation-delay: calc(var(--step-duration, 750ms) * -0.5); - } +.runner-shadow { + position: absolute; + bottom: -8rpx; + width: 120rpx; + height: 12rpx; + background: radial-gradient( + ellipse at center, + rgba(0, 0, 0, 0.45), + transparent 70% + ); + border-radius: 50%; + transform-origin: center; } -@keyframes foot-step-right { - 0%, - 100% { - transform: translateY(0) rotate(0deg); +/* 跟节拍同步:1 拍 1 次律动 */ +.walker.playing .runner { + animation: runner-bob var(--step-duration, 750ms) ease-in-out infinite; + /* 高 BPM 时加速度模糊,让"跑得很快"有视觉表达 */ + filter: drop-shadow(0 4rpx 12rpx rgba(0, 0, 0, 0.25)); +} + +.walker.playing .runner-shadow { + animation: runner-shadow-pulse var(--step-duration, 750ms) ease-in-out infinite; +} + +/* 跑步律动:身体上下起伏 + 微妙左右摆动 */ +@keyframes runner-bob { + 0% { + transform: translateY(0) rotate(0deg) scale(1); } 25% { - transform: translateY(-40rpx) rotate(8deg); + /* 第一拍着地半程,身体最低 */ + transform: translateY(2rpx) rotate(-1.5deg) scale(1, 0.99); } 50% { - transform: translateY(-2rpx) rotate(0deg); + /* 离地最高点,身体抬起 */ + transform: translateY(-14rpx) rotate(0deg) scale(1, 1.01); } 75% { - transform: translateY(0) rotate(0deg); + /* 另一脚着地半程,反向倾斜 */ + transform: translateY(2rpx) rotate(1.5deg) scale(1, 0.99); + } + 100% { + transform: translateY(0) rotate(0deg) scale(1); } } -@keyframes foot-step-left { + +@keyframes runner-shadow-pulse { 0%, 100% { - transform: scaleX(-1) translateY(0) rotate(0deg); - } - 25% { - transform: scaleX(-1) translateY(-40rpx) rotate(8deg); + opacity: 0.5; + transform: scaleX(1); } 50% { - transform: scaleX(-1) translateY(-2rpx) rotate(0deg); - } - 75% { - transform: scaleX(-1) translateY(0) rotate(0deg); - } -} -@keyframes shadow-pulse { - 0%, - 100% { - opacity: 0.55; - transform: translateX(-50%) scaleX(1); - } - 25% { - opacity: 0.18; - transform: translateX(-50%) scaleX(0.5); - } - 50% { - opacity: 0.7; - transform: translateX(-50%) scaleX(1.08); + /* 跳起时阴影变小变淡 */ + opacity: 0.2; + transform: scaleX(0.7); } } diff --git a/TUICallKit-Vue3/static/training/runner.png b/TUICallKit-Vue3/static/training/runner.png new file mode 100644 index 00000000..7a83be7f Binary files /dev/null and b/TUICallKit-Vue3/static/training/runner.png differ