Html Video 显示到 Canvas 中

Video 视频画面加载到 Canvas 中并限制显示区域与缩放

简介

由于项目需要在视频上放大指定区域播放、视频滚轮缩放、绘制特定内容,H5 原生的 Video 控件无法满足需求。但是同样的 Canvas 也有不如 Video 的弊端,比如全屏。

方法

requestVideoFrameCallback

HTMLVideoElement.requestVideoFrameCallback() 用于注册回调,在渲染一帧图像时触发。
参考博客:The requestVideoFrameCallback API

回调播放核心代码
1
2
3
4
5
6
7
8
9
10
const video = document.querySelector("video");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

const updateCanvas = (now, metadata) => {
ctx.drawImage(video, 0, 0, width, height);
video.requestVideoFrameCallback(updateCanvas);
};

video.requestVideoFrameCallback(updateCanvas);
回调播放演示

基于回调的区域裁切

通过创建 Canvas 控件时的 drawImage 方法控制裁切显示区域
参考:Web Api drawImage
例如:裁切起始坐标 150,150,裁切大小 576x324,显示坐标 0,0,显示大小 384x216

核心代码
1
2
3
4
5
6
7
8
9
10
11
12
const startDrawingCutting = () => {
const video = document.querySelector("video");
const canvas = document.getElementById('videoCutting');
const ctx = canvas.getContext("2d");

const updateCanvasCutting = (now, metadata) => {
ctx.drawImage(video, 150, 150, 576, 324, 0, 0, 384, 216);
video.requestVideoFrameCallback(updateCanvasCutting);
};
video.requestVideoFrameCallback(updateCanvasCutting);
};
window.addEventListener('load', startDrawingCutting);
回调裁切演示

Konva.js

Konva.js 是适用于桌面/移动端应用的 HTML5 2d canvas 库,将视频添加到 Konva 的舞台中,更适合后期操作。
参考:VideoOnCanvas 将视频加载到 Konva Canvas 中

Konva 播放核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var layer = new Konva.Layer();
stage.add(layer);
var video = document.createElement('video');
var image = new Konva.Image({
image: video,
draggable: true,
x: 0,
y: 0,
});
layer.add(image);
var anim = new Konva.Animation(function () {
// do nothing, animation just need to update the layer
}, layer);
// update Konva.Image size when meta is loaded
video.addEventListener('loadedmetadata', function (e) {
image.width(width);
image.height(height);
});
Konva 播放演示

基于 Konva.js 的拖拽和鼠标滚轮缩放

  1. 拖拽:创建 Konva 对象时设置 draggable: true 即可拖动
    参考 复杂的拖拽区域 可以设置更为详细的拖拽规则
  2. 缩放:监听 wheel 方法进行缩放操作
鼠标滚轮缩放核心代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var scaleBy = 1.04;
stageZoom.on('wheel', e => {
e.evt.preventDefault();
var oldScale = stageZoom.scaleX();
var mousePointTo = {
x: stageZoom.getPointerPosition().x / oldScale - stageZoom.x() / oldScale,
y: stageZoom.getPointerPosition().y / oldScale - stageZoom.y() / oldScale
};
var newScale =
e.evt.deltaY < 0 ? oldScale * scaleBy : oldScale / scaleBy;
stageZoom.scale({ x: newScale, y: newScale });
var newPos = {
x:
-(mousePointTo.x - stageZoom.getPointerPosition().x / newScale) *
newScale,
y:
-(mousePointTo.y - stageZoom.getPointerPosition().y / newScale) *
newScale
};
stageZoom.position(newPos);
stageZoom.batchDraw();
});
拖拽和鼠标滚轮缩放演示