如何将 GIF 帧转换为 spritesheet
how to convert frames of GIF into spritesheet
我正在尝试合并 GIF 中的多个帧以将它们转换为 spritesheet。我以某种方式能够使用 libgif.js 提取帧
这是我的代码。 Canvas 我想放我所有图片的地方是空的,最后我不知道它有什么问题。
<img hidden src="https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif" rel:auto_play="0"
rel:rubbable="0" />
<div id="frames">
</div>
<canvas id="myCanvas" style="border:1px solid #d3d3d3;">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/jsgif@1.0.2/libgif.js"></script>
<script>
$(document).ready(function () {
$('img').each(function (idx, img_tag) {
var total = 0;
if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
var rub = new SuperGif({ gif: img_tag, progressbar_height: 0 });
rub.load(function () {
for (var i = 0; i < rub.get_length(); i++) {
total += 1;
rub.move_to(i);
var canvas = cloneCanvas(rub.get_canvas());
$("#frames").append('<img id = "' + i + '"src= "' + canvas + '">');
}
for (var i = 0; i <= total; i++) {
id = i.toString();
var img = document.getElementById(id);
window.onload = function () {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.drawImage(img, 10, 10);
}
}
});
}
});
});
function cloneCanvas(oldCanvas) {
var img = oldCanvas.toDataURL("image/png");
return img;
}
</script>
您的解决方案中的主要问题是您正在遍历所有插入的帧图像并使用 window.onload
并期望在 canvas 上绘制图像。但是,在图像元素之后,您在图像元素上分配了windows.onload
,图像已经在之前的(for i = 0)
迭代中附加到dom,通过$("#frames").append(...
。这意味着您的 onload
处理程序在事件已经触发后注册。
我将您的代码重新排列到下面的代码片段中,以确保在将图像帧附加到文档之前注册 onload
。
在这个解决方案中,我通过一个接一个地垂直放置图像帧来创建“spritesheet”。相应地调整解决方案以创建您想要的“spritesheet 布局”。
棘手的部分是您需要以动态方式为 canvas 设置 width
和 height
,这意味着您必须等待所有图像帧完成将 loaded
放入文档中并测量它们的总宽度和高度。
算法应该是:
- 收集图像帧的所有宽度和高度
onload
- 计算总数
canvas.width
和 canvas.height
取决于
你想要的布局(在我的垂直其中一个解决方案中
这意味着使用最大图像宽度作为 canvas 宽度和
所有图像高度的总和作为高度。如果你需要一个不同的
spritesheet 布局然后你需要以不同的方式调整这个逻辑)
- 画完canvas上的所有图片,至此已经足够了
宽度和高度以适合您所有的 gif 帧图像。
在我的解决方案中我没有实现这个算法,我宁愿在为您的特定 gif 示例手动计算 max-img-width 和 total-img-height 之后硬编码 canvas 宽度和高度。
$(document).ready(function () {
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
let canvasWidth = 0;
let canvasHeight = 0;
$('img').each(function (idx, img_tag) {
var total = 0;
if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
var rub = new SuperGif({ gif: img_tag, progressbar_height: 0 });
rub.load(function () {
for (let i = 0; i < rub.get_length(); i++) {
total += 1;
rub.move_to(i);
var canvas = cloneCanvas(rub.get_canvas());
const img = $('<img id = "' + i + '"src= "' + canvas + '">');
img.on('load', function() {
// draw the image
ctx.drawImage(this, 0, canvasHeight);
// extend canvas width, if newly loaded image exceeds current width
canvasWidth = $(this).width() > canvasWidth ? $(this).width() : canvasWidth;
// add canvas height by the newly loade image height value
canvasHeight += $(this).height();
// resize sprite-canvas to host the new image
canvas.width = canvasWidth;
canvas.height = canvasHeight;
});
$("#frames").append(img);
}
});
}
});
});
function cloneCanvas(oldCanvas) {
var img = oldCanvas.toDataURL("image/png");
return img;
}
Gif:
<img hidden src="https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif" rel:auto_play="0"
rel:rubbable="0" />
<hr />
Frames:
<div id="frames">
</div>
<hr />
Canvas:
<hr />
<canvas id="myCanvas" style="border:1px solid #d3d3d3;" width="400" height="17600">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/jsgif@1.0.2/libgif.js"></script>
我正在尝试合并 GIF 中的多个帧以将它们转换为 spritesheet。我以某种方式能够使用 libgif.js 提取帧 这是我的代码。 Canvas 我想放我所有图片的地方是空的,最后我不知道它有什么问题。
<img hidden src="https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif" rel:auto_play="0"
rel:rubbable="0" />
<div id="frames">
</div>
<canvas id="myCanvas" style="border:1px solid #d3d3d3;">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/jsgif@1.0.2/libgif.js"></script>
<script>
$(document).ready(function () {
$('img').each(function (idx, img_tag) {
var total = 0;
if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
var rub = new SuperGif({ gif: img_tag, progressbar_height: 0 });
rub.load(function () {
for (var i = 0; i < rub.get_length(); i++) {
total += 1;
rub.move_to(i);
var canvas = cloneCanvas(rub.get_canvas());
$("#frames").append('<img id = "' + i + '"src= "' + canvas + '">');
}
for (var i = 0; i <= total; i++) {
id = i.toString();
var img = document.getElementById(id);
window.onload = function () {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.drawImage(img, 10, 10);
}
}
});
}
});
});
function cloneCanvas(oldCanvas) {
var img = oldCanvas.toDataURL("image/png");
return img;
}
</script>
您的解决方案中的主要问题是您正在遍历所有插入的帧图像并使用 window.onload
并期望在 canvas 上绘制图像。但是,在图像元素之后,您在图像元素上分配了windows.onload
,图像已经在之前的(for i = 0)
迭代中附加到dom,通过$("#frames").append(...
。这意味着您的 onload
处理程序在事件已经触发后注册。
我将您的代码重新排列到下面的代码片段中,以确保在将图像帧附加到文档之前注册 onload
。
在这个解决方案中,我通过一个接一个地垂直放置图像帧来创建“spritesheet”。相应地调整解决方案以创建您想要的“spritesheet 布局”。
棘手的部分是您需要以动态方式为 canvas 设置 width
和 height
,这意味着您必须等待所有图像帧完成将 loaded
放入文档中并测量它们的总宽度和高度。
算法应该是:
- 收集图像帧的所有宽度和高度
onload
- 计算总数
canvas.width
和canvas.height
取决于 你想要的布局(在我的垂直其中一个解决方案中 这意味着使用最大图像宽度作为 canvas 宽度和 所有图像高度的总和作为高度。如果你需要一个不同的 spritesheet 布局然后你需要以不同的方式调整这个逻辑) - 画完canvas上的所有图片,至此已经足够了 宽度和高度以适合您所有的 gif 帧图像。
在我的解决方案中我没有实现这个算法,我宁愿在为您的特定 gif 示例手动计算 max-img-width 和 total-img-height 之后硬编码 canvas 宽度和高度。
$(document).ready(function () {
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
let canvasWidth = 0;
let canvasHeight = 0;
$('img').each(function (idx, img_tag) {
var total = 0;
if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
var rub = new SuperGif({ gif: img_tag, progressbar_height: 0 });
rub.load(function () {
for (let i = 0; i < rub.get_length(); i++) {
total += 1;
rub.move_to(i);
var canvas = cloneCanvas(rub.get_canvas());
const img = $('<img id = "' + i + '"src= "' + canvas + '">');
img.on('load', function() {
// draw the image
ctx.drawImage(this, 0, canvasHeight);
// extend canvas width, if newly loaded image exceeds current width
canvasWidth = $(this).width() > canvasWidth ? $(this).width() : canvasWidth;
// add canvas height by the newly loade image height value
canvasHeight += $(this).height();
// resize sprite-canvas to host the new image
canvas.width = canvasWidth;
canvas.height = canvasHeight;
});
$("#frames").append(img);
}
});
}
});
});
function cloneCanvas(oldCanvas) {
var img = oldCanvas.toDataURL("image/png");
return img;
}
Gif:
<img hidden src="https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif" rel:auto_play="0"
rel:rubbable="0" />
<hr />
Frames:
<div id="frames">
</div>
<hr />
Canvas:
<hr />
<canvas id="myCanvas" style="border:1px solid #d3d3d3;" width="400" height="17600">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/jsgif@1.0.2/libgif.js"></script>