react 自定义音频组件样式

utils.js

// 时间格式转换
export const msToTime = (duration) => {
  return moment.utc(duration).format('HH:mm:ss')
}
复制代码

自定义音频: 此组件原始音频标签由于业务需求将标签dom传入组件,需要自己举一反三将标签dom放入该组件。

import React, { useEffect, useState } from 'react';
import './styles.less';
import classNames from 'classnames';
import { msToTime } from './utils.js';
import { Icon, Slider, Menu, Dropdown } from 'antd';

const CustomizeAudio = (props) => {
  const { audioDom } = props
  const [duration, setDurention] = useState(0)
  const [currentTime, setCurrentTime] = useState(0)
  const [playIcon, setPlayIcon] = useState('play-circle')
  const [sliderValue, setSliderValue] = useState(0)
  const [clickPlayFlag, setClickPlayFlag] = useState(false)

  useEffect(() => {
    getDurationTime()
    timeUpdate()
    audioPlaying()
    audioPause()
  }, [])

  // 获取总时长
  const getDurationTime = () => {
    audioDom.load()
    audioDom.ondurationchange = () => {
      setDurention(audioDom.duration)
    }
  }

  // 音频开始播放
  const audioPlaying = () => {
    audioDom.onplaying = () => {
      setPlayIcon('pause-circle')
    }
  }

  // 音频播放时时间位置跟着变化
  const timeUpdate = () => {
    audioDom.ontimeupdate = () => {
      // 初始总时长为NaN
      if (audioDom.duration) {
        setCurrentTime(audioDom.currentTime)
        setSliderValue(parseInt((audioDom.currentTime / audioDom.duration) * 100))
        if (audioDom.currentTime == audioDom.duration) {
          setPlayIcon('play-circle')
        }
      }
    }
  }

  // 音频暂停播放
  const audioPause = () => {
    audioDom.onpause = () => {
      setPlayIcon('play-circle')
    }
  }

  // 点击播放按钮
  const clickPlayBtn = () => {
    if (audioDom.paused) {
      audioDom.currentTime = currentTime
      audioDom.play()
      setClickPlayFlag(true)
    } else {
      setClickPlayFlag(false)
      audioDom.pause()
    }
  }

  // 拖动滑块
  const sliderChange = (value) => {
    setSliderValue(value)
    setPlayProgress(value)
  }

  // 设置播放进度
  const setPlayProgress = (value) => {
    const currentTime = value / 100 * audioDom.duration
    audioDom.currentTime = currentTime
    setCurrentTime(currentTime)
    // 当前处于播放状态,需要暂停播放
    if (!audioDom.paused) {
      audioDom.pause()
    }
  }

  // 滑块停止滑动后
  const sliderAfterChange = () => {
    // 判断滑块暂停后是否需要开启播放
    clickPlayFlag && clickPlayBtn()
  }

  // 调整播放倍速
  const [playSpeed, setPlaySpeed] = useState('1')
  const adjustmentPlaySpeed = ({ key }) => {
    setPlaySpeed(key)
    audioDom.playbackRate = key
  }
  const menu = (
    <Menu onClick={adjustmentPlaySpeed} selectedKeys={[playSpeed]}>
      {['0.25', '0.5', '0.75', '1', '1.25', '1.5', '1.75', '2'].map(doubleSpeed => <Menu.Item key={doubleSpeed}>{doubleSpeed}</Menu.Item>)}
    </Menu>
  )

  return (
    <div className='audioContainer'>
      <div className='playIcon'><Icon type={playIcon} theme="filled" onClick={() => clickPlayBtn()} /></div>
      <div className={classNames('currentTime', 'time')}>{msToTime(currentTime * 1000)}</div>
      <div className='progressBar'><Slider value={sliderValue} tooltipVisible={false} onChange={sliderChange} onAfterChange={sliderAfterChange} /></div>
      <div className={classNames('duration', 'time')}>{msToTime(duration * 1000)}</div>
      <Dropdown overlay={menu} placement="topLeft" trigger={['click']} overlayClassName='playSeedMenu' getPopupContainer={trigger => trigger.parentNode}>
        <div className='multiple'>{playSpeed}x</div>
      </Dropdown>
    </div>
  )
}

export default CustomizeAudio

复制代码

styles.less

.audioContainer {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  padding: 10px 25px;
  border-radius: 35px;
  background-color: #F1F3F4;

  .playIcon {
    margin-right: 26px;
    cursor: pointer;
    color: @primary-color;
    font-size: 26px;
  }

  .time {
    color: rgba(0, 0, 0, .85);
    font-family: PingFangSC-Regular, PingFang SC;
    font-size: 16px;
    font-weight: 400;
    line-height: 22px;
  }

  .currentTime {
    margin-right: 12px;
  }

  .progressBar {
    width: 373px;
    margin-right: 12px;

    .ant-slider .ant-slider-rail {
      background-color: #E1E1E1;
    }
  }

  .duration {
    margin-right: 18px;
  }

  .multiple {
    cursor: pointer;
    color: #000000;
    font-size: 12px;

    &:hover {
      color: @primary-color;
    }
  }
}

.playSeedMenu {
  overflow-x: hidden;
  overflow-y: auto;
  width: 100px;
  max-height: 150px;
}

复制代码

音频自定义样式.png

分类:
前端
标签: