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 ( ) { }, layer); video.addEventListener ('loadedmetadata' , function (e ) { image.width (width); image.height (height); });
Konva 播放演示
基于 Konva.js 的拖拽和鼠标滚轮缩放
拖拽:创建 Konva 对象时设置 draggable: true 即可拖动 参考 复杂的拖拽区域 可以设置更为详细的拖拽规则
缩放:监听 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 (); });
拖拽和鼠标滚轮缩放演示