Developer handoff

频谱播放态移交说明

本页面为只读演示。参数已锁定,不提供暂停、强度或蒙层尺寸调节。左侧效果和下方规格共同构成交付基准。

固定参数 · 持续播放状态

最终参数

声音强度
0.90 / 高
蒙层宽度
83%
蒙层高度
48%
频谱区域
394 × 344
线条宽度
3px
线条间距
4px
垂直中轴
172px
背景色
#9F3224

实现规则

  • 线条是一套固定图层,不允许每根线单独伸缩或位移。
  • 动画对象只有不可见的闭合 Mask 路径;Mask 只控制线条显隐,自身不可渲染。
  • 线条使用纵向渐变:5% 透明 → 50% rgba(255,255,255,.1) → 95% 透明。
  • 波形上下共用同一幅度并锁定在 172px 中轴,避免播放时发生整体上下抖动。
  • 禁止加入逐帧随机噪声;音量目标值必须经过平滑插值后再更新 Mask。

图层结构(从下到上)

01页面背景
#9F3224
02固定条纹层
394 × 344;3px 线 + 4px 间距;本层永远不改变几何尺寸。
03垂直渐变
作为条纹自身 Alpha:5% 透明、50% 10% 白、95% 透明。
04动态波形 Mask
只更新闭合路径;白色区域显示条纹,透明区域隐藏条纹。
05业务 UI
封面、文字和按钮位于频谱之上,不参与 Mask。

运行时数据契约

输入
targetEnergy ∈ [0,1]
本演示固定基准
baseEnergy = 0.90
平滑系数
0.08 / frame@60Hz
相位速度
2.88 rad/s
路径采样
24 segments
Mask 边缘模糊
7px
生产接真实音频:仅将模拟的 targetEnergy 替换为 RMS/音量归一化结果。不要把音量直接映射到每根条纹高度。

iOS 实现建议

模块UIKit / Core Animation
固定条纹容器内生成 57 个 CAGradientLayer;每条宽 3pt,起点间隔 7pt。创建后 frame 不再变化。
纵向渐变colors 为透明 / 10% 白 / 透明;locations 为 0.05 / 0.50 / 0.95。
动态蒙层条纹容器的 layer.mask 使用 CAShapeLayer;逐帧只更新 path。
Mask 柔边闭合路径 Alpha 做 7pt Gaussian Blur 后作为 Mask;可用 Core Image 生成 Alpha Mask 并复用渲染资源,禁止模糊最终 UI。
帧驱动使用 CADisplayLink,根据 deltaTime 推进 phase;禁止假定固定 60Hz。
音频输入由 AVAudioEngine tap 或现有播放器分析模块提供 0...1 RMS。
性能要求关闭路径隐式动画:CATransaction.setDisableActions(true);不要每帧重建 57 个条纹层。

Android 实现建议

模块View / Canvas(Compose 同理)
固定条纹自定义 View 中预生成条纹 Bitmap,或一次性绘制到离屏 Layer;3dp 宽,起点间隔 7dp。
纵向渐变条纹 Paint 使用垂直 LinearGradient:5% 透明 / 50% 10% 白 / 95% 透明。
动态蒙层用 Path 生成闭合波形;离屏绘制条纹后通过 DST_IN 合成 Mask。Compose 可用 BlendMode.DstIn。
Mask 柔边Mask Paint 使用 7dp BlurMaskFilter;Compose 可通过原生 Paint maskFilter 后再做 DstIn。
帧驱动使用 Choreographer.FrameCallback 或 Compose withFrameNanos,根据 deltaTime 推进 phase。
音频输入由现有播放器可视化接口、PCM/RMS 分析模块提供 0...1 值;不要使用系统输出音量。
性能要求缓存条纹 Bitmap/Picture;每帧只重建波形 Path 并重绘 Mask,不重新创建 Shader 和条纹对象。

两端共用的波形算法

size = 394 × 344
centerY = 172
segments = 24
halfWidth = 83 / 200
baseEnergy = 0.90

每帧:
phase += deltaTime × 2.88
targetEnergy = clamp(audioRMS, 0, 1)
smoothingAlpha = 1 - pow(0.92, deltaTime × 60)
smoothedEnergy += (targetEnergy - smoothedEnergy)
                  × smoothingAlpha

for i = 0...24:
  x = i / 24
  centered = (x - 0.5) / halfWidth
  window = 1 - smoothstep(
    0.72, 1.08, abs(centered)
  )

  shape = max(0.12,
    0.52 + 0.22*sin(x*9.5  + phase*0.72)
         + 0.18*sin(x*23   - phase*1.06 + 0.7)
         + 0.09*sin(x*49   + phase*1.52 + 2.1)
         + 0.10*sin(x*5.2  - phase*0.44)
  )

  maxAmplitude = 18 + 48*2.2*smoothedEnergy
  amplitude = (1.8*window + maxAmplitude*shape)
              * window

  top[i]    = (x*394, 172-amplitude)
  bottom[i] = (x*394, 172+amplitude)

用 Catmull-Rom → cubic Bézier 连接 top;
反向连接 bottom;闭合后作为 Alpha Mask。

所有尺寸先按 375pt/dp 设计基准计算,再由容器整体等比缩放。不要分别缩放线宽、间距和路径坐标。

验收清单

  • 暂停逐帧观察时,所有竖条纹的 x、宽度和间距保持不变。
  • Mask 不得以色块、光斑或半透明形状出现在最终画面。
  • 播放过程中波形中心始终保持在 172px,不发生整体上下跳动。
  • 60Hz 与 120Hz 设备上的动画速度一致。
  • UI 层不受频谱 Mask 影响,封面与文字不得发生透明度变化。

左侧演示仅用于确认最终视觉;本文件的交付对象为 iOS 与 Android 原生开发。