这些调色板循环图简直让人惊叹:http://www.effectgames.com/demos/canvascycle/?sound=0
我想把它们中的一些(或全部)做成桌面背景。
我可以使用动画 gif 版本,但是我不知道如何从画布“动画”中获取它。是否有什么工具可用于完成此类工作(特别针对该链接和一般情况)。
这些调色板循环图简直让人惊叹:http://www.effectgames.com/demos/canvascycle/?sound=0
我想把它们中的一些(或全部)做成桌面背景。
我可以使用动画 gif 版本,但是我不知道如何从画布“动画”中获取它。是否有什么工具可用于完成此类工作(特别针对该链接和一般情况)。
我有一个解决方案,但是它需要您熟悉Firefox(安装Firebug插件)、Chrome或Safari的Javascript控制台。
如果您不熟悉,请Google它,或在页面上右键单击任何地方,选择“检查元素”,然后查找“控制台”...
代码功能:
它允许您每1/10秒拍摄10个CANVAS
元素的屏幕截图。这两个值都很容易修改,因为您可以调整以找到所需的迭代次数。对于您给出的示例,画布元素ID为“mycanvas”。
一旦它获得了屏幕截图,就会将图像输出到页面中。此时,您可以保存单个图像。
运行代码:
将以下代码粘贴到Javascript控制台中:
var canvas = document.getElementById("mycanvas");
var shots = [];
var grabLimit = 10; // Number of screenshots to take
var grabRate = 100; // Miliseconds. 500 = half a second
var count = 0;
function showResults() {
//console.log(shots);
for (var i=0; i<shots.length; i++) {
document.write('<img src="' + shots[i] + '"/>\n');
}
}
var grabber = setInterval(function(){
count++;
if (count>grabLimit) {
clearInterval(grabber);
showResults();
}
var img = canvas.toDataURL("image/png");
shots.push(img);
}, grabRate);
按下CTRL-Enter以执行它。
运行需要几秒钟,请耐心等待。
完成后,您应该拥有创建动画GIF所需的全部框架(可能还有更多),可通过ImageMagick、此网站MakeAGif.com或其他应用程序创建动画GIF。
附注
如果由于某种原因您需要输出为GIF或JPG而不是PNG,请根据需要更新以下内容:
var img = canvas.toDataURL("image/png");
变成下列其中一个:
var img = canvas.toDataURL("image/gif");
var img = canvas.toDataURL("image/jpg");
支持输出为gif或jpg的功能可能并不在所有浏览器中可用(大多数浏览器应该都支持)。
(大)更新#1
首先,我保留了上面的代码而不是更新它,因为两种方法都可能对其他人有帮助。
其次,这段新代码并没有解决问题。它几乎可以做到,但有一个主要的缺点。它创建了一个动画GIF(耶!),但它是各种绿色的(噢!)。不确定如何/为什么,但也许有人可以接手并看看我错过了什么。
所以我们开始吧...同样的规则适用-将其复制并粘贴到浏览器的Javascript控制台中(在Firefox中会有一些延迟,但在Google Chrome中运行得相当快...大约需要10秒钟左右)。
var jsf = ["/Demos/b64.js", "LZWEncoder.js", "NeuQuant.js", "GIFEncoder.js"];
var head = document.getElementsByTagName("head")[0];
for (var i=0;i<jsf.length;i++) {
var newJS = document.createElement('script');
newJS.type = 'text/javascript';
newJS.src = 'http://github.com/antimatter15/jsgif/raw/master/' + jsf[i];
head.appendChild(newJS);
}
// This post was very helpful!
// http://antimatter15.com/wp/2010/07/javascript-to-animated-gif/
var w = setTimeout(function() { // give external JS 1 second of time to load
console.log('Starting');
var canvas = document.getElementById("mycanvas");
var context = canvas.getContext('2d');
var shots = [];
var grabLimit = 10; // Number of screenshots to take
var grabRate = 100; // Miliseconds. 500 = half a second
var count = 0;
function showResults() {
console.log('Finishing');
encoder.finish();
var binary_gif = encoder.stream().getData();
var data_url = 'data:image/gif;base64,'+encode64(binary_gif);
document.write('<img src="' +data_url + '"/>\n');
}
var encoder = new GIFEncoder();
encoder.setRepeat(0); //0 -> loop forever, 1+ -> loop n times then stop
encoder.setDelay(500); //go to next frame every n milliseconds
encoder.start();
var grabber = setInterval(function(){
console.log('Grabbing '+count);
count++;
if (count>grabLimit) {
clearInterval(grabber);
showResults();
}
var imdata = context.getImageData(0,0,canvas.width,canvas.height);
encoder.addFrame(context);
}, grabRate);
}, 1000);
它使用了一些有用的代码、指针和JS文件,这些都在这篇博客文章中引用:JavaScript to (Animated) GIF。我直接使用了一些JS文件,但如果你要频繁使用它,你应该将这些文件复制到本地。
对我来说,输出结果是这个GIF:
所以这算是一个东西,但可能不是你需要的...
编辑:最终将代码投入使用,这是结果:
Imagick生成了一张大图,因此我使用gimp进行了优化。
客户端代码是Michael代码的修改版本:
var canvas = document.getElementById("mycanvas");
var shots = [];
var grabLimit = 30; // Number of screenshots to take
var grabRate = 100; // Miliseconds. 500 = half a second
var count = 0;
function postResults() {
console.log("START---------");
for (var i = 0; i < shots.length; i++) {
document.write(shots[i]+"<br />");
}
console.log("END-----------");
}
var grabber = setInterval(function(){
count++;
if (count>grabLimit) {
clearInterval(grabber);
postResults();
}
var img = canvas.toDataURL("image/png");
shots.push(img.replace("data:image/png;base64,",""));
}, grabRate);
这段代码将会在屏幕上输出一些base64字符串。复制并保存到文本文件中,然后上传到您的Web服务器上。接着运行下面的脚本,它会将图像写入您的Web服务器。生成的图像可能会很大且可能会有卡顿,在GIMP中打开并进行优化处理和转换为GIF格式。保存时,强制所有帧使用相同的延迟时间,以使动画更加流畅。
使用PHP实现可能不太难。
既然已经有一种不错的JS解决方案了,如果您希望自动化处理,则可以添加服务器端代码:
<?php
$imageData = array_map('rtrim', file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); //base 64 strings separated by newlines
$delay = 100;
$filename = 'coolmoviebro.gif';
$gif = new Imagick();
for($i = 0; $i < count($imageData); $i++) {
$tempImg = new Imagick();
$tempImg->readimageblob(base64_decode($imageData[$i]));
$gif->addImage($tempImg);
}
$gif->setFormat('gif');
$gif->setImageDelay($delay);
$gif->writeImages($filename, true);
?>
我已经有一两年没写过PHP了,所以请务必仔细检查所有内容等等。
我看了一下代码,似乎只需要进行一些小改动就可以实现。
通过查看Palette.Cycles中的循环对象列表,您应该能够使用cycle.high、cycle.low和cycle.rate字段确定每个循环的周期长度。不过,对于cycle.reverse的六种可能值,您需要使用不同的算法。
一旦您知道了列表中每个循环的长度(如果我正确地阅读了代码,则为毫秒),您可以找到所有循环长度的最小公倍数,这将告诉您动画的总长度。不过,在实践中,您需要首先将它们按样本周期向下取整(例如,每秒十帧的100毫秒),以获得更小的公倍数。
然后在main.js中设置animate函数以接受tickCount参数,并将其传递到palette.cycle中,而不是使用基于实际时间的任何内容。每次迭代增加tick计数器的采样周期。
从那里开始,您应该能够修改Bitmap类的render方法,添加必要的逻辑来将画布拆分为文件。似乎有一些库可以为您管理这个最后的部分。建议使用tick计数作为文件名保存文件(前面加上足够数量的前导零以保持顺序)。使用合适的软件批量将所有图像拼接成一个动态GIF可能是可行的。
当然,我实际上还没有尝试过这个。您可能需要进行检查,例如确保您不会遇到具有史诗般循环长度并在硬盘上创建数百万个图像的动画。
此外,如果愿意再花一些功夫,您还可以确定下一个更新的确切时间并进行不规则采样,但您必须找出如何存储该延迟信息,以便将其用于组装完成的GIF。
这个脚本可以保存100帧。
var webPage = require('webpage');
var fs = require('fs');
var page = webPage.create();
var NB_FRAME = 100;
var current = 0;
page.open('http://www.effectgames.com/demos/canvascycle/?sound=0',
function(status) {
if (status === "success") {
var current = 0;
var grabber = setInterval(function () {
var frame = page.evaluate(function() {
return document.getElementById('mycanvas').toDataURL("image/png").split(",")[1];
});
fs.write("./frame-" + current + ".png",atob(frame), 'wb');
if (++current === NB_FRAME) {
window.clearInterval(grabber);
phantom.exit(0);
}
}, 1000);
}
});
运行它:
phantomjs SaveCanvasFrame.js
convert *.png animated.gif
很遗憾,根据艺术创作者的说法,由于图片的不同部分具有不同的周期,将其转换为GIF动画并不是完全可能的。