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;
width: 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, width: 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={{ width: 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);
}
}
}
}

react video的更多相关文章

  1. React 基于antd+video.js实现m3u8格式视频播放及实时切换

    文档连接地址(官网看起麻烦,看中文别人整理好的)https://blog.csdn.net/a0405221/article/details/80923090 React项目使用  安装依赖 npm ...

  2. Redux React & Online Video Tutorials

    Redux React & Online Video Tutorials https://scrimba.com/@xgqfrms https://scrimba.com/c/cEwvKNud ...

  3. React Native 的ES5 ES6写法对照表

    模块 引用 在ES5里,如果使用CommonJS标准,引入React包基本通过require进行,代码类似这样: //ES5 var React = require("react" ...

  4. React Native开发技术周报2

    (1).资讯 1.React Native 0.22_rc版本发布 添加了热自动重载功能 (2).技术文章 1.用 React Native 设计的第一个 iOS 应用 我们想为用户设计一款移动端的应 ...

  5. React的第一步

    首先了解React中所牵扯到的几个重要的概念 什么是React? 是Facebook的开发团队开发出来的一个用于构建用户界面个js库,最近才开源出来公布于世,它的初衷是用于创建“独立的视图组件”,一个 ...

  6. React/React Native 的ES5 ES6写法对照表

    //es6与es5的区别很多React/React Native的初学者都被ES6的问题迷惑:各路大神都建议我们直接学习ES6的语法(class Foo extends React.Component ...

  7. React v16-alpha 从virtual dom 到 dom 源码简读

    一.物料准备 1.克隆react源码, github 地址:https://github.com/facebook/react.git 2.安装gulp 3.在react源码根目录下: $npm in ...

  8. 【React Native 实战】微信登录

    1.前言 在今天无论是游戏开发还是app开发,微信作为第三方登录必不可少,今天我们就用react-native-wechat实现微信登录,分享和支付同样的道理就不过多的介绍了. 2.属性 1)regi ...

  9. React Native视频播放(iOS)

    网站链接:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/learn-react-native-video/ React Nativ ...

  10. [React Native] Complete the Notes view

    In this final React Native lesson of the series we will finalize the Notes view component and squash ...

随机推荐

  1. 552. 学生出勤记录 II (Hard)

    问题描述 552. 学生出勤记录 II (Hard) 可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤.迟到.到场).记录中只含下面三种字符: 'A':Absent,缺勤 ...

  2. linux安装grafana成功后,登录成功,几天后无法访问

    页面提示: 解决方法: 扩展磁盘空间 检查浏览器版本:升级浏览器版本

  3. 字符类型(char)

    字符类型(char) 基本介绍 字符类型可以表示`单个字符`,字符类型是char,char是两个字节(可以存放汉字),多个字符我们用字符串String(我们后面详细讲解String) 案例演示 //演 ...

  4. 人脸识别:face_recognition初尝试

    在学习face_recognition之前先看git上的另一个项目:face_collection .face_collection某种程度上可以看做是demo,便于我们更好的理解和使用face_re ...

  5. 使用shell判断文件夹中是否包含文件

    #!/bin/bash directory="/path/to/directory" if [ $(ls -A $directory) ]; then echo "有文件 ...

  6. .net core格式化响应数据(json驼峰格式)

    //表格字段都是大写的 想要实现首字母小写(特定操作配置输出序列化选项)[HttpPost, ActionName("QueryAll")] public ActionResult ...

  7. CentOS系统上离线部署MySQL

    卸载自带Mariadb 1.[卸载前确认系统是首次安装使用,以防止误删用户数据],初次安装默认系统会自带Mariadb,卸载moriadb. 操作方式: 查找:# rpm -qa|grep maria ...

  8. JavaScript&TypeScript学习总结

    目录 一.JavaScript学习总结 1.什么是JavaScript 2.变量 3.变量命名 4.操作符 5.遍历语句 6.函数 7.对象 8.数组 二.TypeScript学习总结 1.什么是Ty ...

  9. Hadoop完全分布式开发配置流程

    完全分布式开发 整体流程 1.准备3台纯净虚拟机 2.修改每台ip,主机名,主机映射,关闭防火墙 3.安装jdk和hadoop,配置环境变量 4.集群分发脚本编写 5.集群配置 6.ssh免密登录 7 ...

  10. 原生django怎么给响应头添加信息

    原生django怎么给响应头添加信息 直接在HttpResponse响应对象中添加键值对就行 视图层 ---------------------- def test_func(request): # ...