React 音乐播放器

本文使用React利用Html 的audio组件 制作一个简单的音乐播放器;

本文代码参考博文:https://blog.csdn.net/sinat_39626276/article/details/81034385 有兴趣的可以去这个博主那里看代码;

贴代码 先是 jsx部分:

import React from 'react';
import styles from './Index.module.scss';
import videoPlay from '../img/videoPlay.png'
import videoPause from '../img/videoPause.png'

class Audio extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            isDrag: false,//是否拖动
            isPlay: false,//是否播放
            isGet: false,//获取时长
            duration: '', //时间长度
            currentTime: '00:00',//当前时间
        }
    }

    audio = React.createRef();

    //播放音频 
    playRecord = () => {

        if (!this.state.isPlay) {
            this.setState({
                isPlay: true,
                isGet: true,
                duration: this.timeParse(this.audio.current.duration)
            }, () => {
                this.audio.current.play();
            })
        } else {
            this.setState({
                isPlay: false
            }, () => {
                this.audio.current.pause();
            })

        }
        时间监听函数 update
        this.audio.current.ontimeupdate = () => {
            if (this.state.isPlay) {
                let percent = this.audio.current.currentTime / this.audio.current.duration * 100;
                this.inner.style.width = percent + '%'
                this.setState({
                    currentTime: this.timeParse(this.audio.current.currentTime)
                })
                if (percent === 100) {
                    this.setState({
                        isPlay: false
                    }, () => {
                        setTimeout(() => {
                            this.inner.style.width = '0%'
                            this.setState({
                                currentTime: '00:00'
                            })
                        }, 0.5)
                    })
                }
            }
        }

    }

    //拖动 点击事件
    move = (e) => {
        if (e.target.id !== 'line')
            return;
        const { offsetX } = e.nativeEvent;
        const { offsetWidth } = e.target;
        const percent = offsetX / offsetWidth;
        this.inner.style.width = percent * 100 + '%';
        this.audio.current.currentTime = percent * this.audio.current.duration;
        this.setState({
            currentTime: this.timeParse(this.audio.current.currentTime)
        })
    }

    //点击事件
    clcikLine = (e) => {
        this.move(e)
    }

    //拖动事件
    handleMouseMove = (e) => {
        if (this.state.isDrag) {
            this.move(e)
        }
    }

    //鼠标抬起
    handleMouseUp = () => {
        this.setState({
            isDrag: false
        })
    }

    //鼠标放下
    handleMouseDown = () => {
        this.setState({
            isDrag: true
        })
    }

    // 时间一位数时加0
    pad = (val) => {
        const sVal = Math.floor(val); // 舍弃毫秒
        if (sVal < 10) return `0${sVal}`;
        return Number.isNaN(sVal) ? '00' : sVal.toString();
    }

    // 时间格式化为xx:xx
    timeParse = (sec) => {
        const min = Math.floor(sec / 60);
        const secVal = sec - min * 60;
        return `${this.pad(min)}:${this.pad(secVal)}`;
    }


    render() {

        const { isGet, duration, currentTime } = this.state;

        return (
            
{ this.line = line; }}> { this.inner = inner; }} >
{currentTime}
{ isGet ?
{duration}
: '' }
) } } export default Audio;

这里优化了之前博主拖动的代码,但由于我刚转前端CSS还是搞不定 ,拖动不丝滑,具体原因就是获取div组件的问题,有空继续优化css,然后事件效果。

以下是CSS代码,改了之前博主的 写的很凌乱。。

.play {
    width: 100%;
    height: 30%;
    padding: 0 40px;
    margin-top: 10px;
    display: flex;
    .palyButton {
        width: 30px;
        height: 30px;
        background-color: white;
        cursor: pointer;
        background-repeat: no-repeat;
        padding-left: 20px;
        flex: 1;
        position: relative;
        .icon {
            bottom: 10px;
            position: absolute;
        }
    }
    .line {
        flex: 8;
        width: 95%;
        height: 4px;
        position: relative;
        .text1 {
            position: absolute;
            top: 10px;
            left: 0px;
        }
        .text2 {
            position: absolute;
            top: 10px;
            right: 0px;
        }
        .lineWrap {
            width: 100%;
            height: 100%;
            background-color: #C4C4C4;
            display: inline-block;
            cursor: pointer;
            .lineInner {
                width: 0%;
                height: 5px;
                display: inline-block;
                background-image: linear-gradient(to right, #4B94FF, #4B93FF, #79DDFC);
                position: relative;
                bottom: 11px;
                pointer-events: none;
                .lineDot {
                    pointer-events: all;
                    position: absolute;
                    top: -6px;
                    right: -10px;
                    width: 20px;
                    height: 20px;
                    display: inline-block;
                    background-image: url('../img/Ellipse45.png');
                    background-repeat: no-repeat;
                }
            }
        }
    }
}

总的来说完成了效果,但是很不丝滑,拖动效果 需要重新根据css写,目前还是没有搞定多个DIV嵌套下事件触发及获取位置的方法,原博主的计算方式没太看懂,大体是通过计算整个屏幕的,总之太烦了,想要获取上上一级父物体的相对位置写法目前还没,有大神指导下么。

最后效果图如下,需要的可以直接拿去用。目前有三个问题:css写的乱,拖动事件不丝滑,还有就是在componentDidMount 生命周期拿不到audio具体的数组会报空和NaN,不知道为啥,所以一开始没有拿到audio的时间,有兴趣的小伙伴可以改下。

你可能感兴趣的:(React,css,js,javascript,前端,react)