diff --git a/TUICallKit-Vue3/pages/training/metronome.vue b/TUICallKit-Vue3/pages/training/metronome.vue index 8ab0863b..7a2f443a 100644 --- a/TUICallKit-Vue3/pages/training/metronome.vue +++ b/TUICallKit-Vue3/pages/training/metronome.vue @@ -17,99 +17,65 @@ - - - - - - {{ walkerTip }} - - {{ statusHint }} - - - - - - - - - - - - 每分钟 - - {{ bpm }} - - - - - 每步耗时 - - {{ intervalMs }} - ms - - - - 动画速度 - - {{ playbackRate.toFixed(2) }} - × - - - + + + + - - - - - −10 - - - −1 - - - +1 - - - +10 - + + + + {{ p.icon }} + {{ p.name }} + {{ p.bpm }} BPM + {{ p.desc }} + - - - - 每组拍数 - - - {{ m.label }} - + + + + + 微调 + + + + + + + {{ m.label }} + @@ -129,13 +95,42 @@ const RUNNER_VIDEO_URL = 'https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/video/20260525/20260525164014ef89f8862.mp4' /** - * 视频原速对应的 BPM 基准 - * runner.mp4 时长 0.97s, 一个 walk cycle (左右脚各一次) ≈ 124 BPM 步频 - * 用户调速时 playbackRate = bpm / VIDEO_BASE_BPM - * 微信小程序限制 playback-rate 范围 [0.5, 2.0] + * 视频原速对应的 BPM 基准(参见 hooks 实现注释) + * playback-rate 范围 [0.5, 2.0] */ const VIDEO_BASE_BPM = 124 +/** + * 推荐档位:覆盖大多数老人健走场景,一键切换 BPM + 拍号 + * 不在档位的中间数值用右下角微调即可 + */ +const PRESETS = [ + { + id: 'slow', + icon: '🚶', + name: '慢走', + bpm: 80, + accent: 4, + desc: '热身 · 恢复', + }, + { + id: 'normal', + icon: '🏃‍♀️', + name: '健走', + bpm: 110, + accent: 4, + desc: '日常 · 通勤', + }, + { + id: 'brisk', + icon: '🏃', + name: '快走', + bpm: 130, + accent: 4, + desc: '提速 · 燃脂', + }, +] as const + const METER_OPTIONS = [ { label: '2', value: 2 }, { label: '3', value: 3 }, @@ -151,7 +146,6 @@ const metronome = useMetronome({ const { bpm, isPlaying, - beatIndex, isAccent, accentEvery, intervalMs, @@ -180,6 +174,19 @@ const togglePlay = () => { } } +/* 当前命中的档位(BPM + 拍号都匹配才算选中) */ +const activePreset = computed(() => { + const hit = PRESETS.find( + (p) => p.bpm === bpm.value && p.accent === accentEvery.value, + ) + return hit?.id ?? null +}) + +const applyPreset = (p: (typeof PRESETS)[number]) => { + setBpm(p.bpm) + setAccentEvery(p.accent) +} + /* 视频实例与 BPM 同步 */ let videoCtx: UniApp.VideoContext | null = null @@ -190,7 +197,6 @@ const playbackRate = computed(() => { onMounted(() => { videoCtx = uni.createVideoContext('runner-video') - /* 进页面默认让视频保持暂停,跟节拍器 isPlaying 状态同步 */ setTimeout(() => videoCtx?.pause(), 50) }) @@ -205,13 +211,11 @@ const onVideoError = (e: any) => { const onVideoLoaded = (e: any) => { console.log('[runner-video] metadata loaded:', e?.detail) - /* 元数据加载完后再设 playbackRate,部分基础库初始化时设非 1.0 会卡 */ try { videoCtx?.playbackRate?.(playbackRate.value) } catch (_) {} } -/* 节拍器状态变化 → 同步视频播放/暂停 */ watch(isPlaying, (playing) => { if (playing) { videoCtx?.play() @@ -220,7 +224,6 @@ watch(isPlaying, (playing) => { } }) -/* BPM 变化 → 调整视频播放速度(部分基础库需要手动 API 调用) */ watch(playbackRate, (rate) => { try { videoCtx?.playbackRate?.(rate) @@ -232,29 +235,6 @@ const rootStyle = computed(() => ({ '--step-duration': `${intervalMs.value}ms`, })) -const statusHint = computed(() => { - if (isPlaying.value) { - const cur = ((beatIndex.value - 1) % accentEvery.value) + 1 - return `第 ${cur} 拍 / 共 ${accentEvery.value} 拍` - } - return '轻点中央圆点开始' -}) - -const walkerTip = computed(() => { - if (bpm.value < 70) return '慢走 · 热身' - if (bpm.value < 100) return '健走 · 日常' - if (bpm.value < 130) return '快走 · 提速' - if (bpm.value < 170) return '慢跑 · 有氧' - return '快跑 · 高强' -}) - -const badgeClass = computed(() => { - if (bpm.value < 100) return 'badge-mild' - if (bpm.value < 130) return 'badge-mid' - if (bpm.value < 170) return 'badge-strong' - return 'badge-hot' -}) - onShow(() => { preload() }) @@ -273,33 +253,37 @@ onUnmounted(() => { diff --git a/TUICallKit-Vue3/static/training/audio/click-wood.mp3 b/TUICallKit-Vue3/static/training/audio/click-wood.mp3 index a6127c85..4f89ad7a 100644 Binary files a/TUICallKit-Vue3/static/training/audio/click-wood.mp3 and b/TUICallKit-Vue3/static/training/audio/click-wood.mp3 differ diff --git a/TUICallKit-Vue3/static/training/audio/click.mp3 b/TUICallKit-Vue3/static/training/audio/click.mp3 index a25fa2b0..d56c0dd0 100644 Binary files a/TUICallKit-Vue3/static/training/audio/click.mp3 and b/TUICallKit-Vue3/static/training/audio/click.mp3 differ