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;
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的更多相关文章
- React 基于antd+video.js实现m3u8格式视频播放及实时切换
文档连接地址(官网看起麻烦,看中文别人整理好的)https://blog.csdn.net/a0405221/article/details/80923090 React项目使用 安装依赖 npm ...
- Redux React & Online Video Tutorials
Redux React & Online Video Tutorials https://scrimba.com/@xgqfrms https://scrimba.com/c/cEwvKNud ...
- React Native 的ES5 ES6写法对照表
模块 引用 在ES5里,如果使用CommonJS标准,引入React包基本通过require进行,代码类似这样: //ES5 var React = require("react" ...
- React Native开发技术周报2
(1).资讯 1.React Native 0.22_rc版本发布 添加了热自动重载功能 (2).技术文章 1.用 React Native 设计的第一个 iOS 应用 我们想为用户设计一款移动端的应 ...
- React的第一步
首先了解React中所牵扯到的几个重要的概念 什么是React? 是Facebook的开发团队开发出来的一个用于构建用户界面个js库,最近才开源出来公布于世,它的初衷是用于创建“独立的视图组件”,一个 ...
- React/React Native 的ES5 ES6写法对照表
//es6与es5的区别很多React/React Native的初学者都被ES6的问题迷惑:各路大神都建议我们直接学习ES6的语法(class Foo extends React.Component ...
- React v16-alpha 从virtual dom 到 dom 源码简读
一.物料准备 1.克隆react源码, github 地址:https://github.com/facebook/react.git 2.安装gulp 3.在react源码根目录下: $npm in ...
- 【React Native 实战】微信登录
1.前言 在今天无论是游戏开发还是app开发,微信作为第三方登录必不可少,今天我们就用react-native-wechat实现微信登录,分享和支付同样的道理就不过多的介绍了. 2.属性 1)regi ...
- 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 ...
- [React Native] Complete the Notes view
In this final React Native lesson of the series we will finalize the Notes view component and squash ...
随机推荐
- 552. 学生出勤记录 II (Hard)
问题描述 552. 学生出勤记录 II (Hard) 可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤.迟到.到场).记录中只含下面三种字符: 'A':Absent,缺勤 ...
- linux安装grafana成功后,登录成功,几天后无法访问
页面提示: 解决方法: 扩展磁盘空间 检查浏览器版本:升级浏览器版本
- 字符类型(char)
字符类型(char) 基本介绍 字符类型可以表示`单个字符`,字符类型是char,char是两个字节(可以存放汉字),多个字符我们用字符串String(我们后面详细讲解String) 案例演示 //演 ...
- 人脸识别:face_recognition初尝试
在学习face_recognition之前先看git上的另一个项目:face_collection .face_collection某种程度上可以看做是demo,便于我们更好的理解和使用face_re ...
- 使用shell判断文件夹中是否包含文件
#!/bin/bash directory="/path/to/directory" if [ $(ls -A $directory) ]; then echo "有文件 ...
- .net core格式化响应数据(json驼峰格式)
//表格字段都是大写的 想要实现首字母小写(特定操作配置输出序列化选项)[HttpPost, ActionName("QueryAll")] public ActionResult ...
- CentOS系统上离线部署MySQL
卸载自带Mariadb 1.[卸载前确认系统是首次安装使用,以防止误删用户数据],初次安装默认系统会自带Mariadb,卸载moriadb. 操作方式: 查找:# rpm -qa|grep maria ...
- JavaScript&TypeScript学习总结
目录 一.JavaScript学习总结 1.什么是JavaScript 2.变量 3.变量命名 4.操作符 5.遍历语句 6.函数 7.对象 8.数组 二.TypeScript学习总结 1.什么是Ty ...
- Hadoop完全分布式开发配置流程
完全分布式开发 整体流程 1.准备3台纯净虚拟机 2.修改每台ip,主机名,主机映射,关闭防火墙 3.安装jdk和hadoop,配置环境变量 4.集群分发脚本编写 5.集群配置 6.ssh免密登录 7 ...
- 原生django怎么给响应头添加信息
原生django怎么给响应头添加信息 直接在HttpResponse响应对象中添加键值对就行 视图层 ---------------------- def test_func(request): # ...