有没有办法在 canvas 上渲染动画透明 gif 并更改帧之间的延迟
Is there a way to render animated transparent gif on canvas and change the delay between frames
我正在开发一个网站,可以为透明动画 gif(通常来自 giphy)提供 link,我想在 canvas 上渲染它(动画),同时保持动画 gif 的透明度。这样可以改变GIF的动画速度。
我试过使用以下
fastgif
但是三十帧只有一帧显示图像,其余的都是完全透明的。没有透明度的 Gif 也可以。
gifuct-js
但是背景是黑色的,不透明。我知道 gifuct 提供了一个 transparencyIndex 但它在解码 gif 时没有显示。
我试过很多不同的 gif,包括不是来自 giphy 的 Photoshop 和 After Effects 创建的,但没有结果。
fastgif(其中 all
是用 fetch
获取的解码 gif)
import { Decoder } from 'fastgif'
const d = new Decoder()
window.fetch('https://media.giphy.com/media/tTutsU63rnHC8/giphy.gif')
.then((response) => response.arrayBuffer())
.then((buffer) => d.decode(buffer))
.then(async (frames) => {
const canvas = document.createElement('canvas');
canvas.width = all[0].imageData.width;
canvas.height = all[0].imageData.height;
const ctx = canvas.getContext('2d');
let frame = 0;
while (true) {
ctx.putImageData(all[frame].imageData, 0, 0);
await new Promise((resolve) => window.setTimeout(resolve, all[frame].delay));
if (++frame === all.length) {
frame = 0;
}
}
})
gifuct-js
这个我只试了渲染一帧看透明度能不能用,但是背景全黑,一点透明度都没有。
var tempCanvas = document.createElement('canvas')
var tempContext = tempCanvas.getContext('2d')
window.fetch('https://media.giphy.com/media/tTutsU63rnHC8/giphy.gif')
.then((response) => response.arrayBuffer())
.then((buffer) => new GIF(buffer))
.then((gif) => gif.decompressFrames(true))
.then(async (frames) => {
const frame = frames[0]
const dims = frame.dims
c.width = dims.width
c.height = dims.height
tempCanvas.width = dims.width
tempCanvas.height = dims.height
const imageData = tempContext.createImageData(dims.width, dims.height)
tempContext.putImageData(imageData, 0, 0)
// set the patch data as an override
imageData.data.set(frame.patch)
let pix = imageData.data
ctx.clearRect(0, 0, c.width, c.height)
ctx.drawImage(tempCanvas, 0, 0)
ctx.putImageData(imageData, 0, 0)
image.src = tempCanvas.toDataURL('image/png')
})
我希望渲染看起来像将 <img src='https://media.giphy.com/media/tTutsU63rnHC8/giphy.gif' />
添加到网站。透明背景动画。
这是我发现的一种涉及 gifler 和 konvajs 的解决方案:
https://konvajs.org/docs/sandbox/GIF_On_Canvas.html.
Update 这是一个解决方案,其中包括需要调整延迟(注意 onDrawFrame
函数中的注释。
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var layer = new Konva.Layer();
stage.add(layer);
var canvas = document.createElement('canvas');
// use external library to parse and draw gif animation
function onDrawFrame(ctx, frame) {
/*
Here is where you can adust the delay between frames.
*/
frame.delay = 80;
// update canvas that we are using for Konva.Image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(frame.buffer, frame.x, frame.y);
// redraw the layer
layer.draw();
}
gifler('https://media1.giphy.com/media/l4pTpdRiFv10jFlNC/200w_d.gif').frames(canvas, onDrawFrame, true);
// draw resulted canvas into the stage as Konva.Image
var image = new Konva.Image({
image: canvas
});
layer.add(image);
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@3.4.1/konva.min.js"></script>
<script src="https://unpkg.com/gifler@0.1.0/gifler.min.js"></script>
<meta charset="utf-8" />
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
我正在开发一个网站,可以为透明动画 gif(通常来自 giphy)提供 link,我想在 canvas 上渲染它(动画),同时保持动画 gif 的透明度。这样可以改变GIF的动画速度。
我试过使用以下
fastgif
但是三十帧只有一帧显示图像,其余的都是完全透明的。没有透明度的 Gif 也可以。gifuct-js
但是背景是黑色的,不透明。我知道 gifuct 提供了一个 transparencyIndex 但它在解码 gif 时没有显示。
我试过很多不同的 gif,包括不是来自 giphy 的 Photoshop 和 After Effects 创建的,但没有结果。
fastgif(其中 all
是用 fetch
获取的解码 gif)
import { Decoder } from 'fastgif'
const d = new Decoder()
window.fetch('https://media.giphy.com/media/tTutsU63rnHC8/giphy.gif')
.then((response) => response.arrayBuffer())
.then((buffer) => d.decode(buffer))
.then(async (frames) => {
const canvas = document.createElement('canvas');
canvas.width = all[0].imageData.width;
canvas.height = all[0].imageData.height;
const ctx = canvas.getContext('2d');
let frame = 0;
while (true) {
ctx.putImageData(all[frame].imageData, 0, 0);
await new Promise((resolve) => window.setTimeout(resolve, all[frame].delay));
if (++frame === all.length) {
frame = 0;
}
}
})
gifuct-js 这个我只试了渲染一帧看透明度能不能用,但是背景全黑,一点透明度都没有。
var tempCanvas = document.createElement('canvas')
var tempContext = tempCanvas.getContext('2d')
window.fetch('https://media.giphy.com/media/tTutsU63rnHC8/giphy.gif')
.then((response) => response.arrayBuffer())
.then((buffer) => new GIF(buffer))
.then((gif) => gif.decompressFrames(true))
.then(async (frames) => {
const frame = frames[0]
const dims = frame.dims
c.width = dims.width
c.height = dims.height
tempCanvas.width = dims.width
tempCanvas.height = dims.height
const imageData = tempContext.createImageData(dims.width, dims.height)
tempContext.putImageData(imageData, 0, 0)
// set the patch data as an override
imageData.data.set(frame.patch)
let pix = imageData.data
ctx.clearRect(0, 0, c.width, c.height)
ctx.drawImage(tempCanvas, 0, 0)
ctx.putImageData(imageData, 0, 0)
image.src = tempCanvas.toDataURL('image/png')
})
我希望渲染看起来像将 <img src='https://media.giphy.com/media/tTutsU63rnHC8/giphy.gif' />
添加到网站。透明背景动画。
这是我发现的一种涉及 gifler 和 konvajs 的解决方案: https://konvajs.org/docs/sandbox/GIF_On_Canvas.html.
Update 这是一个解决方案,其中包括需要调整延迟(注意 onDrawFrame
函数中的注释。
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var layer = new Konva.Layer();
stage.add(layer);
var canvas = document.createElement('canvas');
// use external library to parse and draw gif animation
function onDrawFrame(ctx, frame) {
/*
Here is where you can adust the delay between frames.
*/
frame.delay = 80;
// update canvas that we are using for Konva.Image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(frame.buffer, frame.x, frame.y);
// redraw the layer
layer.draw();
}
gifler('https://media1.giphy.com/media/l4pTpdRiFv10jFlNC/200w_d.gif').frames(canvas, onDrawFrame, true);
// draw resulted canvas into the stage as Konva.Image
var image = new Konva.Image({
image: canvas
});
layer.add(image);
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@3.4.1/konva.min.js"></script>
<script src="https://unpkg.com/gifler@0.1.0/gifler.min.js"></script>
<meta charset="utf-8" />
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>