使用相机拍摄并实现实时转为GIF动图预览及下载功能
最编程
2024-07-26 12:44:39
...
import { useEffect, useState } from "react";
import { useMediaStream } from "./useMediaStream";
import gifshot from "gifshot";
const posterUrl =
"https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ebdfb2583e3f4a33a72bc6ffd44b42f2~tplv-k3u1fbpfcp-zoom-crop-mark:1512:1512:1512:851.awebp?";
export default () => {
const [dom, setDom] = useState<HTMLVideoElement>();
// 录制标记
const [flag, setFlag] = useState<boolean>(false);
const [cuttImgRUL, setCurrentRUL] = useState<string>(posterUrl);
// GIF的缓存
const [imgs, setImgs] = useState([]);
// 获取数据流
const { mediaStream } = useMediaStream({
audio: false,
video: {
width: 1920,
height: 1080
}
});
// 获取当前帧画面的dataURL
const getCurrenScreen = () => {
const canvas = document.createElement("canvas");
canvas.width = dom.videoWidth;
canvas.height = dom.videoHeight;
const ctx = canvas.getContext("2d");
ctx.drawImage(dom, 0, 0, canvas.width, canvas.height);
const dataURL = canvas.toDataURL("image/png");
return dataURL;
};
// 设置当前帧
const getPic = () => {
setCurrentRUL(getCurrenScreen());
return getCurrenScreen();
};
// 下载截图
const downPic = () => {
const a = document.createElement("a");
a.href = getCurrenScreen();
a.download = "img";
a.click();
a.remove();
};
// 下载GIF
const downGif = () => {
const config = {
fps: 10,
width: 1920,
height: 1080,
images: imgs
};
gifshot.createGIF(config, function (obj) {
if (!obj.error) {
const url = obj.image;
// 下载GIF
const a = document.createElement("a");
a.href = url;
a.download = "img";
a.click();
a.remove();
}
});
};
// 展示截图
const showPic = () => {
const dom = document.querySelector("img");
if (!dom) return;
dom.src = cuttImgRUL as string;
};
// 录制GIF
const getGif = () => {
setFlag(true);
setImgs([]);
const id = setInterval(() => {
const img = getPic();
setImgs((curr) => [...curr, img]);
}, 16.67);
setTimeout(() => {
setFlag(false);
clearInterval(id);
}, 5000);
};
// 预览GIF
const preViewGif = () => {
const newImage = document.querySelector("img");
let idx = 0;
const id = setInterval(() => {
newImage.src = imgs[idx];
idx++;
if (idx === imgs.length - 1) clearInterval(id);
}, 200);
};
// 初始化播放器
useEffect(() => {
if (!dom) return;
dom.srcObject = mediaStream;
dom.onloadeddata = function () {
dom.play();
};
}, [mediaStream, dom]);
// 初始化dom
useEffect(() => {
if (document.querySelector("video")) {
setDom(document.querySelector("video"));
}
}, []);
// 每当当前帧的地址发生变化就展示它
useEffect(() => showPic(), [cuttImgRUL]);
return (
<>
<video poster={posterUrl} width={400} height={300} />
<br />
<button onClick={() => dom.pause()}>暂停</button>
<button onClick={() => dom.play()}>播放</button>
<button onClick={() => getPic()}>截屏</button>
<button onClick={() => downPic()}>下载截图</button>
<button onClick={() => getGif()}>{flag ? "录制中..." : "录制GIF"}</button>
{imgs.length && !flag ? (
<>
<button onClick={() => preViewGif()}>预览GIF</button>
<button onClick={() => downGif()}>下载GIF</button>
</>
) : (
""
)}
<br />
<br />
<img width="500px" alt="img" />
<canvas width="500px" height="300px" />
</>
);
};