pure JavaScriptã§ã¢ãã¡ã¼ã·ã§ã³GIFãä½ã
ããã°ãã¯ãå½æ°çã¹ãã¼ãã®ã¢ãã¡GIFã«ã¤ãã¦ã®ãã¥ã¼ã¹ããå±ããã¾ãã
ä»åã¯ã¯ã©ã¤ã¢ã³ããµã¤ãã®JavaScriptã ãã§ã¢ãã¡ã¼ã·ã§ã³GIFãä½ãæ¹æ³ãå
±æããã¦é ãã¾ãã
ãµã¤ãã¢ãã¡GIFãä½ããã¨æãã¨imagemagickãªã©ã使ã£ã¦ãµã¼ãã¼ãµã¤ãã§å¦çãããã¨æãã¾ãããä»åç´¹ä»ããã®ã¯ãã©ã¦ã¶ã ãã§ã¢ãã¡GIFãä½ãæ¹æ³ã§ãã
jsgif
antimatter15/jsgif · GitHub
jsgifã¨ããJavaScriptã§Canvasãã¢ãã¡GIFã«å¤æãã¦ãããè¶
絶便å©ã©ã¤ãã©ãªãããã®ã§ããã使ãã¾ãã
ååã§ã¢ãã¡GIFãCanvasã§å¶å¾¡åçã§ããã©ã¤ãã©ãªããã£ã¦ããã£ã¡ã®ã»ããæåã§ããããã¨ã¯å¥ã§ãã
ã©ãããAS3ã®ã©ã¤ãã©ãªãJSã«ç§»æ¤ãããã®ã¿ããã§ã½ã¼ã¹ã³ã¼ããèªããã¨ãã¦ãå ¨ç¶åãããªããã©ã便å©ãããã®ã§å ¨é¢ã®ä¿¡é ¼ãããã¦ä½¿ãã¾ãã
ã ããããããªæãã§ä½¿ãããå®éã«ã¯ç»åããã¼ãããã®ãå¾ ããªãã¨ãããªãã
var img1 = new Image(), img2 = new Image(); img1.src = 'sozai/1.jpg'; img2.src = 'sozai/2.jpg'; var encoder = new GIFEncoder(); encoder.setRepeat(0); encoder.setDelay(100); encoder.setSize(100,100); context.drawImage(img1, 0, 0, canvas.width, canvas.height); encoder.addFrame(context); context.drawImage(img1, 0, 0, canvas.width, canvas.height); encoder.addFrame(context); encoder.finish();
æ°ãã¤ãããã¨
ã¯ãã¹ãªãªã¸ã³å¶ç´ã«ããCanvasã®æ±æ
canvasã«ã¯å¤é¨ãã¡ã¤ã³ããèªã¿è¾¼ãã ç»åãæç»ããcanvasã¯"æ±æ"ããã¦ãç»åã¨ãã¦ä¿åãããªã©ãã¼ã¿ãå¼ãåºããã¨ãã§ããªããªãã»ãã¥ãªãã£ä¸ã®å¶ç´ãããã¾ãã
CORS Enabled Image | MDN
jsgifã¯canvasã使ã£ã¦ç»åãã¼ã¿ãå¼ãåºãã¦ããã®ã§ãå¤é¨ãã¡ã¤ã³ããç»åãèªã¿è¾¼ãã§ããå ´å使ããã¨ãã§ãã¾ããã
å¤é¨ãã¡ã¤ã³ã®ç»åã使ã£ã¦ã¢ãã¡GIFãä½ãããå ´åã¯ãCORSãªãããã·ãéããªã©ããå¿
è¦ãããã¾ãã
file://ã§ç»åãåç §ããå ´åãã¯ãã¹ãªãªã¸ã³å¶ç´ã«å¼ã£ãããã®ã§ãé©å½ãªHTTPãµã¼ãã¼ãç«ã¦ã¦åããå¿ è¦ãããã¾ãã
ãã¢
jsgifã使ã£ãã¢ãã¡GIFçæã®ç°¡åãªãã¢ãä½ã£ã¦ã¿ã¾ããã
GIFçæã®å¦çã¯éãã®ã§ãWebWorkerã使ã£ã¦ããã¯ã°ã©ã¦ã³ãã§å¦çãããããã«ãã¦ãã¾ãã
ãã¢ã®æ§åã¯ããããè¦ãã¾ããChromeã§åãã¨æãã¾ããç´ æã«ã¯ãããªãã¯ãã¡ã¤ã³ãªäººç©ç»åã使ç¨ãã¦ãã¾ãã
http://uiureo.github.com/jsgif-demo/
ãããªæãã®ç»åãçæããã¾ãã
client.js
// Array{DOM Image} -> callback(dataURL) function createGIF (args, callback) { var images = args.images || []; var option = { delay: args.delay || 100, repeat: args.repeat || 0, // default: auto loop width: args.width || 400, height: args.height || 400 }; var canvas = $('#canvas')[0]; var context = canvas.getContext('2d'); canvas.width = option.width; canvas.height = option.height; // GIFã¯éæã«ã§ããªãããç½è²ã§å¡ã context.fillStyle = "rgb(255,255,255)"; context.fillRect(0, 0, canvas.width, canvas.height); var worker = new Worker('encoder.js'); worker.postMessage({ cmd: 'start', data: option }); images.forEach(function (image) { context.drawImage(image, 0, 0, canvas.width, canvas.height); // Workerã«ãã¬ã¼ã ã®ãã¼ã¿ãéã worker.postMessage({ cmd: 'frame', data: context.getImageData(0, 0, canvas.width, canvas.height).data }); context.fillRect(0, 0, canvas.width, canvas.height); }); worker.postMessage({ cmd: 'finish' }); worker.onmessage = function (e) { callback('data:image/gif;base64,' + encode64(e.data)); }; } // from https://github.com/antimatter15/jsgif/blob/master/Demos/b64.js function encode64(input) { var output = "", i = 0, l = input.length, key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", chr1, chr2, chr3, enc1, enc2, enc3, enc4; while (i < l) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) enc3 = enc4 = 64; else if (isNaN(chr3)) enc4 = 64; output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4); } return output; } $(function () { var srcs = ['sozai/1.jpg', 'sozai/2.jpg']; var images = srcs.map(function (src) { var image = new Image(); image.src = src; return image; }); // ç»åãå ¨ãã¼ããããã¾ã§å¾ 㤠window.onload = function() { createGIF({ images: images }, function (dataURL) { $("#image").attr('src', dataURL); }); }; }());
encoder.js
WebWorkerã§ã¢ãã¡GIFãçæããé¨åã§ãã
importScripts('LZWEncoder.js', 'NeuQuant.js', 'GIFEncoder.js'); var encoder = new GIFEncoder(); onmessage = function (e) { if (e.data.cmd === "start") { var data = e.data.data; encoder.setRepeat(data.repeat); encoder.setDelay(data.delay); encoder.setSize(data.width, data.height); encoder.start(); } else if (e.data.cmd === "finish") { encoder.finish(); postMessage(encoder.stream().getData()); } else if (e.data.cmd === "frame"){ encoder.addFrame(e.data.data, true); } };
åé¡ç¹
ãã¼ã¿ã大ãããã¦URLã«åã¾ããªã
å°ããç»åãªããªãã¨ãåã¾ã£ã¦URLã§åç
§ã§ãããã©ãã¢ãã¡GIFç¨éã§ã¯ããã¦ãURLã«åã¾ããªããURLãã³ãã¼ãã¦åç
§ã¨ãã§ããªããã¡ãã£ã¨ä¸ä¾¿ã
ãµã¤ãºãã§ãããããååãã¤ãã¦ä¿åãã§ããªãã£ãããããã¤ããã§ããã
ã¾ã¨ã
pure JavaScriptã§ã¢ãã¡GIFãä½ãæ¹æ³ããç´¹ä»ãã¾ããã
ãµã¼ãã¼ãµã¤ããæ¸ããã¨ãªãããã©ã¦ã¶ã ãã§ã¢ãã¡GIFãä½ããã¨ãã§ããã®ã§ã¨ã¦ã便å©ã§ããã
以ä¸ãã¹ãã¼ããã¥ã¼ã¹éå ±ã§ããã