“This is the 22nd day of my participation in the August Gwen Challenge.

Custom player, components are used native, so a little ugly, focus on business logic.

The interface looks something like this. You can look at the interface and imagine in your mind how you would implement this video player. Here are some questions to ask yourself:

  • This component will accept those props
  • How to obtain basic video information, including duration, resolution, etc.
  • How to pause and play
  • How to implement the logic of dragging the progress bar
  • How to handle the loading of initial video loading display
  • How to handle loading when the video is playing

If you’re not sure about the browser’s audio and video apis and don’t know where to start, take a look at my article: Audio and video knowledge in browsers

The overall idea is as follows:

  1. This component takes a video SRC as an argument
  2. Listening to theonLoadedMetadataEvent, get video duration (duration), real width and height (videoWidth,videoHeight)
  3. Call the Play/Pause methods of the video element when play/pause is clicked
  4. Listen while playingonTimeUpdateGets the current Playing time (currentTime) and calculates the progress of the progress bar
  5. Drag the progress bar to set the current video playing time, as shown in Step 4
  6. Loading is displayed when the video is initially loaded. In other words, the loading property is set to true by default during the first rendering of the component, that is, the loading effect is displayed. When the video metadata is loaded, the loading is cancelled
  7. Loading is displayed. The implementation of this feature is listeningonWaitingEvent, cancel loading immediately, and listen toonCanPlayThe event

Code implementation

The code is implemented with React, and the same is true with Vue. Just focus on the business logic. If you want, I can update this article and add Vue code.

Note: Dom native events in React need to be preceded by an ON and written as a hump

function formatDuration(duration) {
    var sec_num = parseInt(duration, 10); // don't forget the second param
    var hours   = Math.floor(sec_num / 3600);
    var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
    var seconds = sec_num - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours; }if (minutes < 10) {minutes = "0"+minutes; }if (seconds < 10) {seconds = "0"+seconds; }return hours+':'+minutes+':'+seconds;
}

import React, { createRef, useState } from 'react'
import './VideoPlayer.css'
function VideoPlayer({src}){
    const videoDom=createRef()
    // The current playback time of the video
    const [curTime,setCurTime]=useState(0)
    // Video length
    const [duration,setDuration]=useState(0)
    // Video status, whether to pause
    const [isPause,setPause]=useState(true)
    // The video is really big
    const [size,setSize]=useState({width:1920.height:1080})
    // The video is loading
    const [waiting,setWaiting]=useState(true)

    // The video metadata was successfully loaded
    const onLoad=(e) = >{
        const {duration,videoWidth,videoHeight}=e.target
        setDuration(duration)
        setSize({width:videoWidth,height:videoHeight})
        setWaiting(false)}// Control playback pause
    const handlePlay=(play) = >{
        const v=videoDom.current
        if(play){
            setPause(false)
            v.play()
        }else{
            setPause(true)
            v.pause()
        }

    }
    // Change video currentTime while dragging slider
    const onSliderChange=(e) = >{
        setCurTime(e.target.value)
        videoDom.current.currentTime=e.target.value

    }
    // Listen to video timeUpdate
    const onTimeUpdate=() = >{
        const v=videoDom.current
        setCurTime(v.currentTime)
        if(v.ended){
            handlePlay(false)
            v.currentTime=0}}// The loading prompt is displayed
    const onWaiting=() = >{
        setWaiting(true)}// Hide the loading prompt when it can play
    const onCanPlay=() = >{
        setWaiting(false)}return <div className="video-wrapper">
            <video ref={videoDom}  src={src} onLoadedMetadata={onLoad} onTimeUpdate={onTimeUpdate} onWaiting={onWaiting} onCanPlay={onCanPlay}  ></video>Loading */} {waiting &&<div className="waiting">loading...</div>}
            <div className="video-controls">{/* Play button */} {isPause?<button onClick={()= >{handlePlay (true)}} ></button>: <button onClick={()= >{handlePlay (false)}} > suspended</button>} {/* Progress bar */}<input type="range" min="0" max={duration}  value={curTime} onChange={onSliderChange}/>{/* Time information and resolution information */}<span>{formatDuration(curTime)}/{formatDuration(duration)}</span>
                <span>{size.width}x{size.height}</span>
            </div>
        </div>
}
export default VideoPlayer

Copy the code

Styles are written a little bit, videoPlayer.css

.video-wrapper{
    width:800px;
}
.video-wrapper>video{
    width: 100%;
}

.video-controls{
    margin-top: 20px;
}
Copy the code

React is not the focus of this article,React is just a carrier, the same logic can be easily implemented with Vue, the focus is on custom video player logic.