「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」
前言
最近有需求需要实现对一个视频的截图,大部分第三方的视频插件底层截图的原理也都是基于canvas的,今天就来用canvas的方法实现一个对视频的截图。
实现视频截图
canvas.getContext("2d").drawImage
canvas实现截图方法实现的原理就是使用的canvas的drawImage方法实现,这个方法能传入的语法格式有三种,分别是:
ctx = canvas.getContext("2d")
ctx.drawImage(image, dx, dy);
ctx.drawImage(image, dx, dy, dWidth, dHeight);
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
传入两个参数
其中,dx 和 dy 是必填参数,它们分别代表着 image的左上角在目标canvas上 X 轴坐标和image的左上角在目标canvas上 Y 轴坐标。
简而言之,就是确定图片在canvas中的位置的。
比如
ctx.drawImage(image, 0, 0)
代表从画布原点坐标开始绘制图片,图片不会被裁剪,宽高比保持不变
传入四个参数
传入的参数要是为四个,那么前两个参数为 dx 和 dy,后两个参数就是 dWidth 和 dHeight:
dWidth 和 dHeight 分别代表着为图片开辟的可用宽高。
简单的说就是设置canvas显示图片的大小,比如:
ctx.drawImage(image, 0, 0, image.width, image.height)
这时候传入的可用宽高和图片完全相同,那么图片就不会被压缩,假设传入
ctx.drawImage(image, 0, 0, image.width, image.height / 2)
那么图片的高就会被压缩一倍:
传入八个参数
如果传入了八个参数,那么新增的四个参数,决定了如何去裁剪得到的图片
其中,前两个 sx 和 sy 决定了图片裁剪开始的坐标,后两个 sWidth 和 sHeight 决定了将会被裁剪区域的大小,比如:
ctx.drawImage(image,0, 0, 1000, 1500, 0, 0, image.width, image.height / 2)
那么得到的图片就会从 (0,0) 开始裁剪 1000宽 和 1500高 的大小。
实现截取视频
drawImage 的参数的第一位,不只是可以出传入image,他可以传入任何的 canvas 图像源,所以我们也可以传入一个video,这样就可以用上述的方法,去获取video此刻的某个位置的截图。
canvas.toDataURL 获取图片的地址
方法返回一个包含图片展示的 data URI 。可以使用 type 参数改变其类型,默认为 PNG 格式。
比如说:
console.log(canvas_.toDataURL("image/jpg"));
img.src = canvas_.toDataURL("image/jpg");
这样我们就能够获得当前截图的 data URI,将其赋给一张img图片,这样我们就能够实现截图功能并且获得截图的 data URI,下面其中一个图是 canvas 的 drawImage 画出来的,是一个 canvas 元素
另一个则是我们赋值出来的img图片,是一个img元素。
结尾放上详细代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>上传视频,进行预览,截取图片,并且获取时长</title>
</head>
<style>
body {
display: flex;
}
</style>
<body>
<div>
<input type="file" onchange="changFile(this)" />
<div id="showVideo"></div>
</div>
<div>
<img id="image" style=" margin: 23px 10px 0 10px;"/>
</div>
<div>
<button onclick="manualCapture()">点击截图</button><br />
<canvas id="canvas_"></canvas>
</div>
<script>
function changFile(ele) {
var videoFile = ele.files[0];
var url = URL.createObjectURL(videoFile);
console.log(url);
var showVideo = document.getElementById("showVideo");
var htmls =
' <video width="400px" id="video" height="auto" autoplay="autoplay" controls > <source src="' +
url +
'">您的浏览器不支持 HTML5 video 元素。</video>';
showVideo.innerHTML = htmls;
}
function manualCapture() {
var video_ = document.getElementById("video");
var canvas_ = document.getElementById("canvas_");
var ctx_ = canvas_.getContext("2d");
const ratio = window.devicePixelRatio || 1;
ctx_.scale(ratio, ratio);
canvas_.width = video_.offsetWidth * ratio;
canvas_.height = video_.offsetHeight * ratio;
console.log(video_.clientHeight, video_.clientWidth);
ctx_.drawImage(video_, 0, 0, canvas_.width, canvas_.height);
var img = document.getElementById("image");
console.log(canvas_.toDataURL("image/jpg"));
img.src = canvas_.toDataURL("image/jpg");
}
</script>
</body>
</html>
总结
本文只是非常简单的使用canvas截取了视频的图片,结合之前讲过的编辑器的自定义编辑,我们是否就能够实现一个一边记笔记一边看视频,并且自定义一个截图按钮呢?
具体的自定义编辑器功能可以看我之前的两片文章,介绍了相关的如何自定义一个编辑器按钮并且扩展它。结合今天的截图功能,就能够实现一个视频截图的功能块了。
带你定义自己的 editor.js 工具 - 掘金 (juejin.cn)
带你定义自己的 editor.js 工具 - 扩展自定义 - 掘金 (juejin.cn)