2010-07-27 17 views
20

Estas imágenes ciclo paleta son impresionantes: http://www.effectgames.com/demos/canvascycle/?sound=0cada marco de un canvas de HTML5

me gustaría hacer algunos (o todos) de estos en los fondos de escritorio.

Podría usar una versión animada de gif, pero no tengo idea de cómo obtener eso del lienzo "animación". ¿Hay algo disponible que pueda hacer algo en este sentido? (Especialmente para ese enlace y en términos generales).

+4

Esos son increíbles, técnica y artísticamente! Lo más cerca que llegué a una respuesta fue esta: http://stackoverflow.com/questions/923885/capture-html-canvas-as-gif-jpg-png-pdf El problema es que, parece que la implementación solo permite la estática imágenes, no animaciones. ¿Tal vez es posible capturar programáticamente cada "cuadro" como una imagen separada y luego unirlos como un GIF? – peterjmag

+0

que simplemente podría funcionar, tal vez deberías hacer una respuesta a tu comentario, así puedo darte los puntos si a nadie se le ocurre una idea :) –

+3

Mi intento es: http://imgur.com/p9gcV.gif –

Respuesta

24

tengo una solución, pero es depende de que estar familiarizado con la consola de Javascript en Firefox (instalar el Firebug plugin), Chrome o Safari.

En caso de que no estés, Google, o tratar de simplemente haga clic derecho en cualquier lugar de la página, seleccione "Inspeccionar elemento " y buscar "consola" ...

Lo que hace el código:

Se le permite tomar 10 pantalla apropiaciones del elemento CANVAS cada 1/10th de un segundo. Ambos valores se modifican fácilmente ya que puede ajustar para encontrar la cantidad de iteraciones que desea obtener. Para el ejemplo que das, el ID del elemento canvas es 'mycanvas'.

Una vez que tiene las capturas de pantalla, envía las imágenes a la página. En ese momento, puede guardar las imágenes individuales.

ejecutar el código

Pegar en el código siguiente en la consola de 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); 

y pulse Ctrl-Enter para ejecutarlo.

Tarda unos segundos en ejecutarse, así que sea paciente.

Después de eso, debe tener todos los marcos necesarios (quizás más) para crear un GIF animado a través de ImageMagick, este sitio web MakeAGif.com, u otra aplicación.

Nota al margen

Si por alguna razón necesita salida como GIF del JPG en lugar de PNG acaba de actualizar, según sea necesario, esto:

var img  = canvas.toDataURL("image/png"); 

a uno de estos:

var img  = canvas.toDataURL("image/gif"); 
var img  = canvas.toDataURL("image/jpg"); 

Soporte para la salida como gif o jpg puede no estar en todos los navegadores (debería ser la mayoría).

(BIG) ACTUALIZACIÓN # 1

En primer lugar, me quedo con el código anterior intacta en lugar de actualizar porque ambos enfoques podrían ser de utilidad para otros.

En segundo lugar, este nuevo código NO RESUELVE el problema. Es algo así como una desventaja importante. Crea un GIF animado (Yipee!) pero está en varios tonos de verde (Boooo!). No estoy seguro de cómo/por qué, pero tal vez alguien puede tomarlo desde aquí y ver lo que me he perdido.

Así que aquí vamos ... se aplican las mismas reglas: copiar y pegar en la Consola JavaScript de un navegador (está rezagado en Firefox pero Google Chrome es bastante rápido ... 10 segundos más o menos para ejecutar).

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); 

Se utiliza algún código útil, punteros y archivos JS referencia en esta entrada del blog JavaScript to (Animated) GIF. Uso algunos archivos JS directamente, pero debe copiarlos localmente si va a usarlos mucho.

La salida para mí era este GIF: alt text

Así que es algo, pero no lo que necesitas ...

+0

Nunca usa la variable 'context' después de declararlo. ¿Tiene algún uso? –

+1

Vaya. Tienes razón. Olvidé eliminarlo He actualizado el código en consecuencia. Gracias por notarlo. – donohoe

+0

esta es una solución fantástica, pero no sé cómo guardar las imágenes en los archivos. Ni DownThemAll ni Opera Links parecen poder ver las imágenes. –

1

Lamentablemente, de acuerdo con art creator, no es posible convertirlo en animación GIF debido a que diferentes partes de la imagen tienen ciclos diferentes.

+1

Creo que, dado que los GIF animados pueden comprimir con bastante efectividad los píxeles coincidentes en todos los fotogramas, el hecho de que ocupe miles de fotogramas no es en realidad un problema tan grande como el artista sospecha. Por supuesto, su estética favorece la economía, por lo que naturalmente se opondría a solo lanzar espacio en el disco duro al problema, ¡pero eso no significa que no sea posible! – WCWedin

+0

Es - simplemente no directamente. +1 a lo que dijo WCWedin también. – donohoe

+0

De acuerdo, entonces solo necesita averiguar el mínimo común denominador de todos los ciclos de animación. Esa será la cantidad de imágenes que necesita guardar. – syockit

12

EDITAR: Finalmente poner ese código para utilizar, aquí está el resultado:

alt text

generado Imagick una imagen de gran tamaño, por lo que siguió adelante y optimizados con gimp.

El código del lado del cliente es una versión modificada del código de 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); 

Se escribirá un manojo de cuerdas base64 a la pantalla. Cópialos y guárdalos en un archivo de texto y luego súbelo a tu servidor web. Luego ejecute el otro script (ver a continuación) y escribirá la imagen en su servidor web. La imagen resultante será grande y posiblemente entrecortada, por lo tanto, abra GIMP y optimice para diferencia y GIF. Al guardar, forzarlo a utilizar el mismo retraso para todos los cuadros para que la animación sea fluida.


Puede que no sea tan difícil usar PHP.

  1. Tome la dataURL (cadena codificada en base64) para cada cuadro con JS y envíelo al servidor.
  2. Decodifica las cadenas base64 y las convierte en objetos Imagick.
  3. Agregue estos objetos Imagick como marcos a un nuevo objeto Imagick.
  4. Guarde el objeto Imagick en el sistema de archivos como un GIF.

desde que Michael ya se registró una buena solución JS, voy a añadir el código del lado del servidor si desea automatizarlo:

<?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); 

?> 

no he escrito mucho PHP de un año o dos, así asegúrate de revisar todo y demás.

+1

No pretendo ser despreciativo (después de todo, este es el esfuerzo más exitoso puesto en esta pregunta), pero quería señalar que su imagen adolece exactamente de la agitación y los bucles torpes que advirtió el artista. La duración del ciclo de la animación final debe elegirse con mucho cuidado para minimizar estos artefactos. Sin embargo, una pequeña prueba y error o algunas matemáticas de papel y lápiz podrían hacer el truco. Buen trabajo. – WCWedin

+1

@WCWedin: estoy de acuerdo, aunque es bastante sencillo hasta el final de la animación donde no terminó donde originalmente comenzó el ciclo, como se esperaba. Hubiera pensado más en ello, pero pensé que una "prueba de concepto" para generar el gif hubiera sido suficiente, y considerando que la respuesta ya había sido elegida en el momento en que se me ocurrió la imagen, había poca motivación continuar. Aunque si alguien puede obtener los datos de fotograma correctos, me alegraría volver a generar el gif. Si tengo tiempo, creo que puedo echarle un vistazo a la fuente para ver si puedo extraer un ciclo completo. –

2

Tomé un vistazo al código, y parece que debería ser posible con un poco de piratería.

Al observar la lista de objetos de ciclo en Palette.Cycles, debe poder determinar la duración del ciclo de cada ciclo con los campos cycle.high, cycle.low y cycle.rate. Dicho esto, necesitarás un algoritmo diferente para cada uno de los seis valores posibles para cycle.reverse.

Una vez que conoce la duración de cada ciclo en la lista (en milisegundos, si estoy leyendo el código correctamente), puede encontrar el múltiplo menos común de todas las longitudes de ciclo, que indica la longitud total de la animación En la práctica, sin embargo, querrá dividirlos en el suelo primero por su período de muestra (por ejemplo, 100 milisegundos por diez cuadros por segundo) para obtener un múltiplo común más bajo.

Luego, configure la función animada en main.js para tomar un parámetro tickCount y pasarlo a palette.cycle, en lugar de usar cualquier cosa en tiempo real. Aumente el conteo de ticks por su período de muestra con cada iteración.

Desde allí, debe poder modificar el método de renderización de la clase Bitmap, agregando la lógica necesaria para copiar el lienzo en un archivo. Parece que hay bibliotecas que pueden administrar este último bit por usted. Yo recomendaría guardar los archivos usando el conteo de ticks como el nombre del archivo (con suficientes ceros iniciales para mantenerlos en orden.) Puede ser posible unir todas las imágenes en un GIF animado para que se ejecute como un trabajo por lotes usando el software correcto.

Por supuesto, no he intentado esto. Es posible que desee colocar comprobaciones, por ejemplo, para asegurarse de no tropezar con una animación con una duración de ciclo épica y la creación de millones de imágenes en su disco duro.

Como un lado, también podría, con un poco más de trabajo, averiguar el tiempo exacto hasta la próxima actualización y tomar muestras irregulares, pero tendría que averiguar cómo almacenar esa información de retraso de manera que pueda Úselo para ensamblar el GIF completo.

1

Try PhantomJS

Este script ahorra 100 marcos.

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); 
} 
}); 

Run que:

phantomjs SaveCanvasFrame.js 

A continuación, utilice ImageMagick

convert *.png animated.gif 

Aquí vamos: animated