zoukankan      html  css  js  c++  java
  • react video

    import React, { useRef, useState, useCallback } from 'react';
    
    import './style.scss';
    const typeCheckFactory = (typeName: string) => {
        return (arg: any) => {
            if (typeof arg == typeName) {
                return true;
            } else {
                return false;
            }
        };
    };
    export const isNumber = typeCheckFactory('number') as (
        arg: any,
    ) => arg is number;
    function setUnit(value: string | number) {
        return isNumber(value)
            ? value + 'px'
            : ~value.indexOf('%') || !/^d+$/.test(value)
            ? value
            : value + 'px';
    }
    function zeroFill(num: number) {
        if (num < 10) {
            return '0' + num;
        }
        return num;
    }
    
    const timerTarget: { bufferTimer: NodeJS.Timeout | null } = {
        bufferTimer: null,
    };
    export default function(props: {
        height: number | string;
         number | string;
        url: string;
        coverImage: string;
    }) {
        const videoHeight = setUnit(props.height);
        const videoWidth = setUnit(props.width);
        const target = useRef<HTMLVideoElement>(null);
        // 0 play, 1 stop, 2 refresh
        const [videoState, setVideoState] = useState<0 | 1 | 2>(0);
        // 声音
        const [voice, setVoice] = useState<1 | 0>(0);
        // 当前时间
        const [currentTime, setCurrentTime] = useState<string | number>(`00:00`);
        // 进度
        const [progress, setProgress] = useState<string | number>(0);
        // 播放完成 1代表完成
        const [over, setOver] = useState<1 | 0>(0);
        function play() {
            target.current && target.current.play();
        }
        function pause() {
            target.current && target.current.pause();
        }
        const toggle = useCallback(
            function(jump = false) {
                if (
                    (videoState == 0 || over == 1 || jump) &&
                    target &&
                    target.current
                ) {
                    const current = target.current;
                    if (over == 1 && !jump) {
                        setProgress(0);
                        setOver(0);
                        current.currentTime = 0;
                    }
                    play();
                    setVideoState(1);
                    timerTarget.bufferTimer = setInterval(function() {
                        const pgs = current.currentTime / current.duration;
                        if (pgs == 1) {
                            timerTarget.bufferTimer &&
                                clearInterval(timerTarget.bufferTimer);
                            setOver(1);
                        }
                        setProgress(pgs * 100 + '%');
                    }, 1000 / 30);
                } else {
                    timerTarget.bufferTimer &&
                        clearInterval(timerTarget.bufferTimer);
                    pause();
                    setVideoState(0);
                }
            },
            [over, videoState],
        );
    
        function toggleVoice(): void {
            setVoice((v) => (1 - v) as 1 | 0);
        }
    
        // 处理秒数为时分秒 h:m:s
        function getTime(num: number) {
            const m = zeroFill(Math.floor(num / 60)),
                remainder = zeroFill(Math.floor(num % 60)),
                time = m + ':' + remainder;
            return time;
        }
        function progressClick(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
            e.stopPropagation();
            const currentTarget = e.currentTarget;
            const barLength = e.pageX - currentTarget.offsetLeft;
            timerTarget.bufferTimer && clearInterval(timerTarget.bufferTimer);
    
            if (target.current) {
                target.current.currentTime =
                    (barLength / currentTarget.clientWidth) *
                    target.current.duration;
                setProgress((barLength / currentTarget.clientWidth) * 100 + '%');
                toggle(true);
            }
        }
        return (
            <div
                className="jdw-video"
                style={{ height: videoHeight,  videoWidth }}
            >
                <div
                    className="mask"
                    onClick={() => {
                        toggle(false);
                    }}
                >
                    {videoState == 0 && <div className="play"></div>}
                    {videoState == 1 && (
                        <div
                            className="toolbar"
                            onClick={(e) => e.stopPropagation()}
                        >
                            <span
                                className="pause"
                                onClick={() => toggle(false)}
                            ></span>
                            <div className="progress" onClick={progressClick}>
                                <div
                                    className="bar"
                                    style={{  progress }}
                                ></div>
                            </div>
                            <span className="timer">
                                {currentTime}/
                                {getTime(
                                    target && target.current
                                        ? target.current.duration
                                        : 0,
                                )}
                            </span>
                            <span
                                className={voice ? 'mute' : 'speak'}
                                onClick={toggleVoice}
                            ></span>
                        </div>
                    )}
                </div>
                <video
                    poster={props.coverImage}
                    ref={target}
                    height={props.height}
                    width={props.width}
                    muted={!!voice}
                    onTimeUpdate={() => {
                        setCurrentTime(
                            getTime(
                                target && target.current
                                    ? target.current.currentTime
                                    : 0,
                            ),
                        );
                    }}
                >
                    <source src={props.url} type="video/ogg" />
                    Your browser does not support the video tag.
                </video>
            </div>
        );
    }
    .video {
        position: relative;
        video {
            position: relative;
            z-index: 0;
        }
        .mask {
            box-sizing: border-box;
            cursor: pointer;
            height: 100%;
            position: absolute;
            width: 100%;
            z-index: 11;
    
            .item {
                background-position: left top;
                background-repeat: no-repeat;
                background-size: cover;
                border-radius: 50%;
                height: 22px;
                left: 50%;
                position: absolute;
                top: 50%;
                transform: translate(-50%, -50%);
                width: 22px;
            }
            .play {
                @extend .item;
                background-image: url(./images/play.png);
            }
            .refresh {
                @extend .item;
                background-image: url(./images/refresh.png);
            }
            .toolbar {
                align-items: center;
                bottom: 0;
                display: flex;
                height: 48px;
                justify-content: space-between;
                left: 20px;
                position: absolute;
                right: 20px;
                .pause {
                    background: url(./images/pause.png) no-repeat center center;
                    background-size: 12px 12px;
                    cursor: pointer;
                    height: 48px;
                    margin-right: 24px;
                    width: 48px;
                }
                .progress {
                    cursor: pointer;
                    flex-grow: 1;
                    flex-shrink: 1;
                    height: 12px;
                    margin-right: 24px;
                    position: relative;
                    &:before {
                        background-color: rgba(255, 255, 255, 0.3);
                        border-radius: 4px;
                        content: '';
                        height: 4px;
                        left: 0;
                        position: absolute;
                        top: 4px;
                        width: 100%;
                    }
                    .bar {
                        height: 12px;
                        min-width: 12px;
                        position: relative;
                        &:before {
                            background-color: #ffffff;
                            border-radius: 50%;
                            content: '';
                            height: 12px;
                            position: absolute;
                            right: 0;
                            top: 0;
                            width: 12px;
                            z-index: 2;
                        }
                        &:after {
                            background-color: rgba(242, 23, 12, 1);
                            border-radius: 4px;
                            content: '';
                            height: 4px;
                            left: 0;
                            position: absolute;
                            top: 4px;
                            width: 100%;
                        }
                    }
                }
                .timer {
                    color: rgba(255, 255, 255, 1);
                    font-size: 20px;
                    height: 48px;
                    line-height: 48px;
                    margin-right: 24px;
                    min-width: 115px;
                }
                .voice {
                    background-position: center center;
                    background-repeat: no-repeat;
                    background-size: 24px 24px;
                    cursor: pointer;
                    height: 48px;
                    width: 48px;
                }
                .mute {
                    @extend .voice;
                    background-image: url(./images/mute.png);
                }
                .speak {
                    @extend .voice;
                    background-image: url(./images/voice.png);
                }
            }
        }
    }
  • 相关阅读:
    Base64的解码和编码
    [WebService]代理类中对枚举类型的序列化
    Linq中的Where与SkipWhile
    Html 5中自定义data*特性
    实用TSQL之生成当前索引数据库中的外键上
    使用Post/Redirect/Get实现Asp.net防止表单重复提交
    用SquishIt最小化Css与Javascript文件
    Asp.net MVC 3 中 Unobtrusive javascript 与Ajax
    HTML5中custom data*特性与asp.net mvc 3 表单验证
    实现Asp.net MVC中AjaxOnly特性
  • 原文地址:https://www.cnblogs.com/hellolol/p/15108326.html
Copyright © 2011-2022 走看看