Dynamically capture the frame display of vedio elements, click on the frame image to jump to playback video
illustrate
Create a simple video timing viewer. When the video is playing, it will periodically grab image frames from the video and draw them canvas
on When the user clicks canvas
on any frame displayed on the , the played video will jump to the corresponding point in time.
Video Timing Viewer
<video controls width="550px" height="310" id="video">
<source src="./告白气球.mp4">
</video>
<canvas id="canvas"></canvas>
Among them video
, canvas
it is used to play the video and draw the captured frame picture. At this point, the video can be displayed, click to play to play, the next thing to do is to get the event processing function when you click to play, regularly capture pictures and draw them on canvas
the canvas
Note:
autoplay
The attribute needs to cooperate withmuted
the attribute , otherwise it cannot be played automatically (because it is afraid that the automatic play will scare you to death, so it must be muted before it can be played automatically, which is very nice)
Dynamically capture vedio element frame display
The event handlers involved are:
- The event handler for click to play is
onplaying
- The event handler for click pause is
onpause
- The event handler function for the end of video playback is
onended
canvas
When using video as the drawing source (context.drawImage(video, picX, picY, picWidth, picHeight)
), what is drawn is only the currently playing frame
<video controls width="550px" height="310" id="video" onplaying="startVideo()" onpause="clearTimer()" onended="clearTimer()">
<source src="./告白气球.mp4">
</video>
let timer = null // 定时器(播放完需要清除)
const timerInterval = 1 // 抓取间隔 s
let picCount = 0 // 当前帧索引
let videoTime = 0 // 资源时长
const picWidth = 110
const picHeight = 62
const xCount = 12
let grid = 0
let canvas = document.querySelector('#canvas')
canvas.width = picWidth * xCount
canvas.style.background = 'beige'
context = canvas.getContext('2d')
let video = document.querySelector('#video')
let videoWidth = video.width
let videoHeight = video.height
video.volume = 0.3 // 设置音量
video.oncanplay = function () {
videoTime = video.duration
let yCount = Math.ceil(videoTime / timerInterval)
grid = xCount * yCount
canvas.height = picHeight * yCount
}
// 开始播放后开始抓图
function startVideo(){
videoShot()
timer = setInterval(videoShot, timerInterval * 1000)
}
// 将抓取的帧绘制到canvas上
function videoShot(){
// %求余数
// picCount: 0,1,2,3,4,....
// picPostion: 0,1,2,3,4,...12,0,1,2,3,4,...12,...
// picX: 0*110, 1*110, 2*110, 0*110,...
// picY: 0, 0, 0, 300, 300, 300, 600, ...
let picPostion = picCount % grid
let picX = (picPostion % xCount) * picWidth
let picY = (Math.floor(picPostion / xCount)) * picHeight
context.drawImage(video, picX, picY, picWidth, picHeight)
picCount++
}
// 播放结束
function clearTimer(){
clearInterval(timer)
}
Note: The duration of obtaining resources
video.duration
needs wait for the resources to be loadedvideo.oncanplay = function () { // 获取时长 }
Click the frame image to jump to playback video
// 开始播放后开始抓图
function startVideo(){
if(timer) {
clearTimer() // 清除定时器
}
videoShot()
timer = setInterval(videoShot, timerInterval * 1000)
}
// 单击canvas上某一帧时定位到视频
canvas.onclick = function(e){
let offX = e.offsetX - canvas.offsetLeft
let offY = e.offsetY - canvas.offsetTop + 310 // 310 是video的高度
// 点击的帧索引值
let clickedFrame = Math.floor(offY / picHeight) * xCount
clickedFrame += Math.floor(offX / picWidth)
// 定位到指定帧位置
video.currentTime = clickedFrame * timerInterval
picCount = clickedFrame
}
Note:
video.currentTime
It willstartVideo
, so it needs to be judgedstartVideo
in to clear the timer
Effect
My Lun is handsome! ! !
The video resources are self-collected.