【MoodVine】Taro+React动画实践

开发中,动画是提升用户体验的关键要素。本文将深入探讨我在 Taro+React 项目中实现的两种动画效果:麦克风录音的呼吸动画和语音消息的波形动画,分享技术实现细节和设计思考。

1. 麦克风呼吸动画:录音状态的可视化反馈

场景需求

当用户开始录音时,我们需要通过视觉反馈让用户明确知道系统正在收音。这种反馈需要:

  • 直观表达"正在录音"的状态
  • 保持愉悦的用户体验
  • 不过度消耗系统资源

实现方案

javascript 复制代码
import Taro, { useRef, useEffect } from '@tarojs/taro'

const RecordButton = ({ isRecording }) => {
  const animationRef = useRef(null)

// 处理录音动画效果useEffect(() => {
    if (!isRecording) return;

    const createAnimation = () => {
// 创建基础动画实例const animation = Taro.createAnimation({
        duration: 800,// 动画持续时间timingFunction: 'ease-in-out'// 缓动函数
      })

// 定义动画关键帧
      animation.scale(1.1).step()// 第一步:放大
      animation.scale(1.0).step()// 第二步:恢复

      return animation;
    }

// 递归动画函数const animate = () => {
      if (!isRecording) return;

      const animation = createAnimation()
      animationRef.current = animation

// 使用requestAnimationFrame确保动画流畅requestAnimationFrame(() => {
        animation.export()
      })

// 递归调用形成循环setTimeout(animate, 1600)// 总动画周期1.6秒
    }

// 启动动画animate();

// 清理函数return () => {
      animationRef.current = null;
    }
  }, [isRecording])

  return (
    <View
      className={`audio-icon ${isRecording ? 'recording' : ''}`}
      animation={animationRef.current}
    >
      <Image src="/assets/microphone.png" />
    </View>
  )
}

对应CSS:

css 复制代码
.audio-icon {
  margin: auto;
  width: 140px;
  height: 140px;
  transition: transform 0.3s ease-in-out;
  background-size: contain;

// 使用CSS动画作为备选方案
  &.recording {
    animation: pulse 1.6s infinite ease-in-out;
  }
}

// 呼吸动画关键帧@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}

技术亮点

  1. 双方案实现

    • 首选Taro的API驱动动画
    • CSS动画作为优雅降级方案
  2. 动画递归调用

    javascript 复制代码
    const animate = () => {
    // 创建动画...setTimeout(animate, 1600)
    }
    animate()

    这种递归模式比setInterval更可控

  3. 性能优化

    • 使用requestAnimationFrame确保流畅性
    • 清理阶段解除引用避免内存泄漏
  4. 参数调优

    • 1.1倍的缩放比例提供足够视觉变化,但不过分夸张
    • 1.6秒周期创造自然的呼吸节奏

2. 语音波形动画:模拟音浪跳动

场景需求

在语音消息气泡中,需要通过动态效果表达:

  • 消息类型是语音而非文本
  • 即使不播放也暗示其动态属性
  • 创建视觉吸引力引导点击

实现方案

javascript 复制代码
const AudioMessage = () => (
  <View className="audio-bubble">
    <View className="audio-wave">
      {[1, 2, 3, 4, 5].map(index => (
        <View
          key={index}
          className="wave-bar"
          style={{
            animationDelay: `${(index-1) * 0.2}s`,
            height: '50%'
          }}
        />
      ))}
    </View>
    <Text>2:36</Text> {/* 语音时长 */}
  </View>
)

对应CSS:

css 复制代码
.audio-bubble {
  display: flex;
  align-items: center;
  padding: 10rpx 20rpx;

// 不同用户类型的样式区分.current-user & {
    background-color: #daf0ff;
  }

  .other-user & {
    background-color: #f0f2f5;
  }
}

.audio-wave {
  display: flex;
  align-items: center;
  height: 40rpx;
  margin-right: 15rpx;

  .wave-bar {
    width: 8rpx;
    height: 30rpx;
    background-color: #1890ff;
    margin: 0 4rpx;
    border-radius: 4rpx;
    animation: wave 1.2s infinite ease-in-out;

// 为每个波形条设置不同的延迟
    &:nth-child(1) { animation-delay: 0s; }
    &:nth-child(2) { animation-delay: 0.2s; }
    &:nth-child(3) { animation-delay: 0.4s; }
    &:nth-child(4) { animation-delay: 0.6s; }
    &:nth-child(5) { animation-delay: 0.8s; }

// 不同用户颜色设置.current-user & {
      background-color: white;
    }
  }
}

@keyframes wave {
  0%, 100% {
    height: 10rpx;
  }
  50% {
    height: 30rpx;
  }
}

技术亮点

  1. 分布式延迟设计

    css 复制代码
    &:nth-child(1) { animation-delay: 0s; }
    &:nth-child(2) { animation-delay: 0.2s; }
    ...

    每个波形柱延迟依次增加0.2秒,创造波浪效果

  2. 振幅控制

    css 复制代码
    @keyframes wave {
      0%, 100% { height: 10rpx; }
      50% { height: 30rpx; }
    }

    中点为最高值,创造真实波形运动感

  3. 动态高度适应

    通过设置起始和结束点为小振幅,中点为高峰值:

    • 更符合声波物理特性
    • 相比0到100%的线性变化更自然
  4. 上下文感知颜色

    css 复制代码
    .current-user .wave-bar {
      background-color: white;
    }

    根据消息来源自动调整颜色,保持设计一致性

动画设计原则

1. 性能优先策略

  • 硬件加速:使用transform而非height/width
  • 层控制:限制will-change使用范围
  • 平衡刷新率:60fps是最佳目标(16.67ms/帧)

2. 用户体验考虑

麦克风动画

  • 持续反馈:明确录音状态
  • 中断复位:停止录音立即回到初始状态
  • 心理模型契合:呼吸模式暗示"活着的"录音状态

波形动画

  • 隐含功能暗示:动态效果暗示点击播放
  • 无声音的预览:即使静音状态也能感知消息类型
  • 节奏引导:波浪方向暗示时间流动