背景
由于开发之前做的VisualDrag拖拽模板优化的时候,拖拽进去的图片、视频文件等需要进行截图作为封面,目前采用的截图方法是htme2canvas,使用canvas进行的截图操作,所以就会遇到这样的问题,视频和图片图床简单的使用标签加入canvas画布里面无法正确的截图成功。最后采取的措施就是将图片转为base64画入canvas,将视频截取第一帧图片,然后画进canvas,最后进行截图,最后经过折腾,这个方法好像成功了,写这篇博客进行记录下。
JS截取视频第一帧
截取视频的第一帧作为视频的封面是一个很常见的视频上传的做法。但这种做法一般会在上传进服务器时,在服务器进行截图了,这个操作方法在我之前的博客上有介绍过:https://qkongtao.cn/?p=560#h2-4
但是前端有时候为了避免浪费服务器资源,可以在前端使用js直接进行截图了。
代码如下:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js截取视频第一帧</title>
</head>
<body>
<div>
<button onclick="cutImage()">截取视频第一帧</button>
</div>
<div>
<!-- 注意跨域画布污染 -->
<video width="640" height="480" src="https://upyun.qkongtao.cn/kodbox/视频/20221016134256839.mp4"
controls="controls" id="fileVideo" crossorigin="anonymous">您的浏览器不支持视频播放</video>
<div>
<p>视频第一帧:</p> <img
src="https://upyun.qkongtao.cn/kodbox/视频/upload.png?_upt=5b974ef11679068799"
id="videoImg">
</div>
</div>
</body>
<script>
function cutImage() {
// 获取音频标签
let video = document.getElementById('fileVideo')
video.currentTime = 2 // 第一帧
video.oncanplay = () => {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d') // 绘制2d
canvas.width = video.clientWidth // 获取视频宽度
canvas.height = video.clientHeight // 获取视频高度
// 利用canvas对象方法绘图
ctx.drawImage(video, 0, 0, video.clientWidth, video.clientHeight)
// 转换成base64形式
let imgUrl = canvas.toDataURL("image/png");
console.log('imgUrl :>> ', imgUrl);
document.getElementById("videoImg").src = imgUrl
}
}
</script>
</html>
效果如下:
需要注意的地方是视频资源跨域导致画布污染的问题,所以需要在video标签加上 crossorigin="anonymous" 。
如果需要截图第2帧以上则需要在video.oncanplay()方法中进行截图。
图片转Base64
在开发的很多场景中需要用到base64图片形式进行传输,这种一般会用在缩略图的小文件图片中,提高浏览器的流畅性。
当然在canvas画布中,当进行绘制图片时,最好还是先将图片img标签转换为base64之后进行drawImage(),避免画布被污染和跨域等问题。
代码如下:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片转Base64</title>
</head>
<body>
<div>
<button onclick="imgToBase64()">转换成base64形式</button>
</div>
<img id="img" src="http://upyun.qkongtao.cn/chevereto/2022/10/28/20210917152407654.jpg" alt="" width="300">
<p>转换成base64形式</p>
<div id="base64" style="word-break: break-all;"></div>
</body>
<script>
function imgToBase64() {
var src = document.getElementById("img").src
getImageUrlBase64(src).then(
(dataUrl) => {
base64Url = dataUrl;
console.log('base64Url :>> ', base64Url);
document.getElementById("base64").innerHTML = base64Url
}
);
}
/**@url :图片服务器上的url
* @img :图片url对应的图片
* */
function getImageUrlBase64(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous"; //处理跨域
img.src = url;
img.onload = function () {
const canvas = document.createElement("canvas"); //创建一个canvas元素
canvas.width = img.width; //把当前url对应的图片的宽度赋予canvas
canvas.height = img.height; //把当前url对应的图片的高度赋予canvas
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); //在画布上一比一的画出img
const dataUrl = canvas.toDataURL("image/jpeg"); //调用canvas的toDataURL获取.jpg的base64数据
resolve(dataUrl);
};
});
}
</script>
</html>
效果如下: