效果:
要点:
- 音频:
<audio src='' controls="controls""></audio>
- 视频:
<video id='video' src='' crossOrigin="anonymous" controls="controls"></video>
react
视频组件:import { Player } from 'video-react'; import '../../../node_modules/video-react/dist/video-react.css' ... <Player ref="player" videoId="video-1" className="video_d"> <source src='' /> </Player>
- 设置视频加载到的时间长度:
const video = document.getElementById('video') video.currentTime = 5//设置视频当前时长
- 获取视频总时长:
const video = document.getElementById('video') video.duration//获取视频总时长
canvas.toDataURL('image/png')
如果该方法提示画布受污染,则在video
标签加上crossOrigin="anonymous"
属性loadeddata
:提示当前帧的数据是可用的;当当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时,会发生loadeddata
事件。video.addEventListener('loadeddata',()=>{});
示例:
video.js:
import React, { Component } from 'react'
import { Player } from 'video-react';
import '../../../node_modules/video-react/dist/video-react.css'
import './video.less'
export default class Video extends Component {
constructor(props) {
super(props)
this.state = {
inputVideoUrl: 'http://wvideo.spriteapp.cn/video/2016/0328/56f8ec01d9bfe_wpd.mp4',
audioUrl: 'http://www.170mv.com/kw/antiserver.kuwo.cn/anti.s?rid=MUSIC_53912340&response=res&format=mp3|aac&type=convert_url&br=128kmp3&agent=iPhone&callback=getlink&jpcallback=getlink.mp3',
video_duration: '',//视频总时长
time_d: 0,//视频当前时长
}
}
componentDidMount() {
const video = document.getElementById('video')
video.currentTime = 5//设置视频当前时长
// loadeddata:提示当前帧的数据是可用的 // 当当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时,会发生 loadeddata 事件。 video.addEventListener('loadeddata', ()=>{ this.captureImage() this.setState({ video_duration: video.duration//获取视频总时长 }, () => { this.mouseMoveFun() }) });
}
// 自动截取视频第一帧作为封面
captureImage() {
const video = document.getElementById('video')
const preview = document.getElementById('preview')
const canvas = document.createElement('canvas') //创建一个canvas
canvas.width = video.offsetWidth
canvas.height = video.offsetHeight
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)//绘制图像
const img = new Image() //创建img
img.src = canvas.toDataURL('image/png') //将绘制的图像用img显示
preview.appendChild(img)
}
// 手动截取视频画面作为封面
buttonFun() {
const canvas = document.getElementById('canvas')
const video = document.getElementById('video')
let context = canvas.getContext('2d');
context.clearRect(0, 0, 400, 200); //清除画布内容
context.drawImage(video, 0, 0, 400, 200);
}
// 监听鼠标在容器内的位置
mouseMoveFun() {
let { video_duration } = this.state
let _this = this
const preview = document.getElementById('preview')
const scrllo_val = document.getElementById('scrllo_val')
preview.onmousemove = function (event) {
event = event || window.event;
//2.获取鼠标在整个页面的位置
let pagex = event.pageX;
let pagey = event.pageY;
//3.获取盒子在整个页面的位置
let xx = preview.offsetLeft;
let yy = preview.offsetTop
//4.用鼠标的位置减去盒子的位置赋值给盒子的内容。
let targetx = pagex - xx;
let targety = pagey - yy;
// this.innerHTML = "鼠标在盒子中的X坐标为:" + targetx + "px;<br>鼠标在盒子中的Y坐标为:" + targety + "px;"
let preview_width = preview.offsetWidth
let time = targetx / preview_width
let time_d = time * video_duration//鼠标当前时长
let scrllo_val_wid = preview_width * time
scrllo_val.style.width = scrllo_val_wid + 'px'//实时更新进度条
_this.setState({
time_d
}, () => {
// console.log(time_d)
if (Number(time_d.toFixed(0)) % 20 == 0) {//避免密集截屏导致卡顿
_this.previewFun()
}
})
}
}
// 鼠标视频实时预览
previewFun() {
let { time_d } = this.state
const canvas = document.createElement('canvas')
const video = document.getElementById('video')
const preview = document.getElementById('preview')
video.currentTime = time_d//设置视频当前时长
let context = canvas.getContext('2d');
context.clearRect(0, 0, 400, 200); //清除画布内容
context.drawImage(video, 0, 0, 400, 200);
const img = new Image() //创建img
img.src = canvas.toDataURL('image/png') //将绘制的图像用img显示
let childImg = preview.childNodes;
if (childImg.length > 1) {
preview.removeChild(childImg[1])//清除已有img
}
preview.appendChild(img)
}
render() {
return (
<div className='video_main'>
<div className='title'>音频播放--audio</div>
<audio src={this.state.audioUrl} controls="controls" className="audio_d">
您的浏览器不支持 audio 标签。
</audio>
<div className='title'>视频播放--Player</div>
<Player ref="player" videoId="video-1" className="video_d">
<source src={this.state.inputVideoUrl} />
</Player>
<div className='title'>视频播放--video</div>
<div id='video_div'>
<video id='video' src={this.state.inputVideoUrl} crossOrigin="anonymous" controls="controls" className="video_d">
您的浏览器不支持 video 标签。
</video>
</div>
<button onClick={this.buttonFun.bind(this)} style={{ margin: '20px' }}>截取视频</button>
<div className='title'>截取视频--canvas</div>
<div className='canvas'>
<canvas id="canvas" width="400" height="200"></canvas>
</div>
<div className='title'>视频预览</div>
<div id='preview'>
<div className='scrllo_bg'>
<div id='scrllo_val'></div>
</div>
</div>
</div>
)
}
}
video.less:
.video_main{
width: 100%;
height: 100vh;
overflow: auto;
.title{
font-size: 24px;
margin: 20px;
}
.video_d{
height: 200px;
width: 400px;
padding: 0px!important;
position: relative;
margin: auto;
.video-react-big-play-button{
position: absolute;
left: 50%;
margin-left: -43px;
top: 50%;
margin-top: -22.5px;
}
}
.audio_d{
width: 400px;
}
.canvas{
width: 400px;
height: 200px;
border: 1px solid red;
margin: auto;
}
#output{
width: 400px;
height: 200px;
border: 1px solid red;
}
#preview{
width: 400px;
height: 200px;
border: 1px solid red;
position: relative;
cursor: pointer;
margin: auto;
img{
width: 100%;
height: 100%;
}
.scrllo_bg{
height: 5px;
width: 100%;
background: gray;
position: absolute;
top: 10px;
opacity: 0;
#scrllo_val{
background: #fff;
height: 100%;
}
}
}
#preview:hover{
.scrllo_bg{
opacity: 1;
}
}
}