electron + vue3 + ts 实现桌面小工具第五天

402 阅读1分钟

electron + vue3 + ts 实现桌面小工具第五天, 使用gif.js

「这是我参与 2022 首次更文挑战的第 2 天,活动详情查看:2022 首次更文挑战

今天要做的工作是尝试对视频进行处理, 在搜索一圈后, 我锁定了 gif.js

引入 gif.js

前提是下载 gif.jsgif.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>

结果

转gif成果.gif