填坑 => Taro InnerAudioContext音频API 无法暂停和停止

738 阅读1分钟

taro填坑之路

音频InnerAudioContext

技术栈=>hooks+TS

填坑.gif

人狠话不多,直接上代码

坑代码

import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import React, { useEffect, useState } from 'react';
import { AtSlider } from 'taro-ui';

interface RecordLineLayoutProps {}
// 进度条录音布局
const RecordLineLayout: React.FC<RecordLineLayoutProps> = ({
}) => {
  const [playing, setPlaying] = useState(false) // 是否播放中
  const [timeText, setTimeText] = useState('') // 总时长
  const [sliderVal, setSliderVal] = useState(0) // 进度条位置
  // 创建音频
  let innerAudioContext = Taro.createInnerAudioContext()
  innerAudioContext.src = ''// 音頻url
  innerAudioContext.onPlay(() => { // 开始
    console.log('开始播放')
    setPlaying(true)
  })
  innerAudioContext.onPause(() => { // 暂停
    console.log('暂停播放');
    setPlaying(false)
  })
  innerAudioContext.onStop(() => {
    console.log('停止');
    setPlaying(false)
  })
  innerAudioContext.onSeeked(() => {
    console.log('跳转');
    innerAudioContext.play()
  })
  innerAudioContext.onTimeUpdate(() => {
    console.log('时间更新', innerAudioContext.currentTime);
    setSliderVal(innerAudioContext.currentTime)
  })
  innerAudioContext.onError((res) => {
    console.log(res.errMsg)
    console.log(res.errCode)
    innerAudioContext.stop()
    setPlaying(false)
  })
  // 切换播放状态
  const changeStatus = () => {
    if (playing) {
      innerAudioContext.pause()
    } else {
      innerAudioContext.play()
    }
  }

  // 拖拽进度条
  const onChange = (e) => {
    console.log('拖拽进度===', e);
    innerAudioContext.seek(e)
  }

  useEffect(() => {
    return () => {
      innerAudioContext.destroy()
    }
  }, []);
  return (
    <View className="recordLineLayoutMap">
      <View className="playBtn" onClick={changeStatus}>开始</View>
      <View className="progressBarBox">
        <AtSlider value={sliderVal} min={0} max={1000} blockSize={15} onChange={onChange} ></AtSlider>
      </View>
      <View className="time" >
        {timeText}
      </View>
    </View>
  );
};

export default RecordLineLayout;

后面发现每次使用useState,都是创建一个新的innerAudioContext实例,导致无法操作到原来的innerAudioContext实例,于是....

正确代码,将innerAudioContext 用useState保存起来,再调用暂停和停止

import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import React, { useEffect, useState } from 'react';
import { AtSlider } from 'taro-ui';
import './RecordLineLayout.scss';


interface RecordLineLayoutProps {
}

// 进度条录音布局
const RecordLineLayout: React.FC<RecordLineLayoutProps> = ({
}) => {
  const [playing, setPlaying] = useState(false) // 是否播放中
  const [timeText, setTimeText] = useState('') // 总时长
  const [sliderVal, setSliderVal] = useState(0) // 进度条位置
  // 创建音频
  let innerAudioContext = Taro.createInnerAudioContext()
  innerAudioContext.src = ''// 音頻url
  innerAudioContext.onPlay(() => { // 开始
    console.log('开始播放')
    setPlaying(true)
  })
  innerAudioContext.onPause(() => { // 暂停
    console.log('暂停播放');
    setPlaying(false)
  })
  innerAudioContext.onStop(() => {
    console.log('停止');
    setPlaying(false)
  })
  innerAudioContext.onSeeked(() => {
    console.log('跳转');
    innerAudioContext.play()
  })
  innerAudioContext.onTimeUpdate(() => {
    console.log('时间更新', audioContextIns.currentTime);
    setSliderVal(audioContextIns.currentTime)
  })
  innerAudioContext.onError((res) => {
    console.log(res.errMsg)
    console.log(res.errCode)
    innerAudioContext.stop()
    setPlaying(false)
  })
  const [audioContextIns, setAudioContextIns] = useState(innerAudioContext)// 音频实例持久化
  // 切换播放状态
  const changeStatus = () => {
    if (playing) {
      audioContextIns.pause()
    } else {
      audioContextIns.play()
    }
  }

  // 拖拽进度条
  const onChange = (e) => {
    console.log('拖拽进度===', e);
    innerAudioContext.seek(e)
  }

  useEffect(() => {
    return () => {
      innerAudioContext.destroy()
    }
  }, []);
  return (
    <View className="recordLineLayoutMap">
      <View className="playBtn" onClick={changeStatus}>开始</View>
      <View className="progressBarBox">
        <AtSlider value={sliderVal} min={0} max={1000} blockSize={15} onChange={onChange} ></AtSlider>
      </View>
      <View className="time" >
        {timeText}
      </View>
    </View>
  );
};

export default RecordLineLayout;