electron + vue3 + ts 实现桌面小工具第五天, 使用gif.js
「这是我参与 2022 首次更文挑战的第 2 天,活动详情查看:2022 首次更文挑战」
今天要做的工作是尝试对视频进行处理, 在搜索一圈后, 我锁定了 gif.js
引入 gif.js
前提是下载 gif.js 和 gif.work.js 在 public 的 gif 文件夹下
引入 gif.js
<script type="text/javascript" src="<%= BASE_URL %>gif/gif.js"></script>
具体操作
选取文件
我们用 input 去选取一个文件
<input ref="input" type="file" @change="fileLoader" />
我们需要一个 video 元素和 canvas 元素
<video ref="video" controls></video> <canvas ref="canvas"></canvas>
并使用 ref 去获取他们
const video = ref(null) as unknown as Ref<HTMLVideoElement>;
const canvas = ref(null) as unknown as Ref<HTMLCanvasElement>;
const input: Ref<HTMLInputElement> = ref() as unknown as Ref<HTMLInputElement>;
在 input 的 change 事件触发后,讲视频播放
const file = input.value.files?.[0] as File;
video.value.src = URL.createObjectURL(file);
video.value.play();
创建 gif.js 的实例
const gif = new GIF({
workers: 2,
quality: 1,
workerScript: process.env.BASE_URL + "gif/gif.worker.js",
width: video.value.width || canvas.value.width,
height: video.value.height || canvas.value.height,
debug: true,
});
创建一个函数, 不停的把 video 的当前帧以图片的形式绘制的 canvas 上。
let AnimationFrame: number;
function switchToCanvas() {
// 将video上的图片的每一帧以图片的形式绘制的canvas上
ctx?.drawImage(video.value, 0, 0, video.value.width, video.value.height);
gif.addFrame(ctx, { copy: true, delay: 33 });
AnimationFrame = window.requestAnimationFrame(switchToCanvas);
}
switchToCanvas();
当视频播放完之后,触发 gif 的 render 函数,并移除 requestAnimationFrame
video.value.addEventListener("ended", function () {
gif.render();
cancelAnimationFrame(AnimationFrame);
});
接下来我们监听,gif 的完成事件, 创建一个 a 标签, 讲我们的 gif 下载下来,
gif.on("finished", function (blob: Blob) {
let url: string = window.URL.createObjectURL(blob);
let link: HTMLAnchorElement = document.createElement("a");
link.href = url;
link.target = "_blank";
link.download = "link.gif";
link.click();
});
完整代码如下
<!--
* @Author: Aisanyi
* @Date: 2022-01-18 11:43:15
* @LastEditors: Aisanyi
* @LastEditTime: 2022-01-20 16:05:39
* @Description: 视频处理
-->
<template>
<input ref="input" type="file" @change="fileLoader" />
<video ref="video" controls></video>
<canvas ref="canvas"></canvas>
</template>
<script lang="ts" setup>
import { ref, Ref } from "vue";
const video = ref(null) as unknown as Ref<HTMLVideoElement>;
const canvas = ref(null) as unknown as Ref<HTMLCanvasElement>;
const input: Ref<HTMLInputElement> =
ref() as unknown as Ref<HTMLInputElement>;
function fileLoader() {
const file = input.value.files?.[0] as File;
video.value.src = URL.createObjectURL(file);
video.value.play();
const ctx = canvas.value.getContext("2d");
// eslint-disable-next-line no-undef
const gif = new GIF({
workers: 2,
quality: 1,
workerScript: process.env.BASE_URL + "gif/gif.worker.js",
width: video.value.width || canvas.value.width,
height: video.value.height || canvas.value.height,
debug: true,
});
let AnimationFrame: number;
function switchToCanvas() {
// 将video上的图片的每一帧以图片的形式绘制的canvas上
ctx?.drawImage(video.value, 0, 0, video.value.width, video.value.height);
gif.addFrame(ctx, { copy: true, delay: 33 });
AnimationFrame = window.requestAnimationFrame(switchToCanvas);
}
switchToCanvas();
console.log(gif);
gif.on("finished", function (blob: Blob) {
let url: string = window.URL.createObjectURL(blob);
let link: HTMLAnchorElement = document.createElement("a");
link.href = url;
link.target = "_blank";
link.download = "link.gif";
link.click();
});
video.value.addEventListener("ended", function () {
console.log("触发结束");
gif.render();
cancelAnimationFrame(AnimationFrame);
});
}
</script>
<style>
canvas {
width: 1000px;
height: 1000px;
}
</style>