var keyframes = { // The habbo preview that was being shown before the user clicked play // We will place this back once they press stop beforePlayImage: null, lastSavedGifURL: null, // list of all keyframe items items: [], // gifjs instance gifjs: null, // init keyframes init: function() { keyframes.add(); }, // add keyframe add: function () { keyframes.items.push({ url: habboCreator.generateUrl() }); // Clear last saved GIF url keyframes.lastSavedGifURL = null; // Update keyframes item list keyframes.ui.updateItems(); // Update keyframes count keyframes.ui.updateCount(); }, // delete keyframe delete: function(self) { var $keyframeItem = $(self).parents('.keyframe-item'); var keyframeData = $keyframeItem.data('keyframe'); // delete from list $keyframeItem.remove(); // remove from array keyframes.items.splice(keyframeData.index, 1); // Clear last saved GIF url keyframes.lastSavedGifURL = null; // Update keyframes item list keyframes.ui.updateItems(); // Update keyframes count keyframes.ui.updateCount(); }, play: function() { if(keyframes.beforePlayImage !== null) { return; } $previewHabboImage = $("#preview-habbo-image"); // Save the current preview URL so we can replace it once gif is stopped keyframes.beforePlayImage = $previewHabboImage.attr('src'); keyframes.getURL(function(url) { $previewHabboImage.attr('src', url); }); }, stop: function() { if(keyframes.beforePlayImage == null) { return; } $previewHabboImage = $("#preview-habbo-image"); $previewHabboImage.attr('src', keyframes.beforePlayImage); keyframes.beforePlayImage = null; }, saveGIF: function() { }, // Get URL and print in console consoleURL: function() { keyframes.getURL(function(url) { console.log(url); }); }, // get GIF url getURL: function(callback) { if(keyframes.lastSavedGifURL == null) { keyframes.generate.createURL(callback); } else { callback(keyframes.lastSavedGifURL); } }, // Generate GIF methods generate: { // Generate the GIF URL createURL: function(callback) { // Show loading keyframes.loading.show(); // Get gif.js instance keyframes.gifjs = getGifInstance(); // Download all images and save to item keyframes.generate.downloadImages(function() { // Preload all the images keyframes.generate.preloadImages(function() { // Add image frames keyframes.generate.addFrames(); // Render finished keyframes.gifjs.on('finished', function(blob) { // After render, upload blob to server and return url keyframes.generate.uploadGIF(blob, function(response) { // Hide loading keyframes.loading.hide(); // Callback callback(response.url); }); }); // Begin render keyframes.gifjs.render(); }); }); }, // Download all images // Images are stored as url_downloaded downloadImages: function(callback) { var ajaxPromises = []; var downloadedCount = 0; var downloadedTotal = keyframes.items.length; for(i in keyframes.items) { var item = keyframes.items[i]; if(typeof item.url_downloaded == 'undefined') { var request = downloadKeyframeURL(item, function (urlDownloaded, item) { // Set downloaded url keyframes.items[item.index].url_downloaded = urlDownloaded; console.log('keyframes: downloaded new url [' + item.index + ']', urlDownloaded); // Set percentage downloadedCount++; var percent = downloadedCount * 100 / downloadedTotal; keyframes.loading.setProgress(percent); }); ajaxPromises.push(request); } } $.when.apply(null, ajaxPromises).done(function() { callback(); }); }, // Preload all downloaded images preloadImages: function(callback) { var imagesTotal = keyframes.items.length; var imagesLoaded = 0; var imageLoadedIncrementer = function() { imagesLoaded++; console.log('keyframes: images loaded ', imagesLoaded, 'out of', imagesTotal); if(imagesLoaded == imagesTotal) { callback(); return; } }; for(i in keyframes.items) { var item = keyframes.items[i]; keyframes.items[i].img = new Image(); keyframes.items[i].img.src = item.url_downloaded; keyframes.items[i].img.addEventListener('load', imageLoadedIncrementer, false); } }, // Add frames to gifjs instance addFrames: function() { for(i in keyframes.items) { var canvas = createCanvasOfImage(keyframes.items[i].img); keyframes.gifjs.addFrame(canvas.getContext('2d'), {delay:200, copy: true}); } }, // Upload gif (blob) to server and return url through callback uploadGIF: function(blob, callback) { var formData = new FormData(); formData.append('_token', CSRF_TOKEN); formData.append('saveBlob', 1); formData.append('image', blob); $.ajax({ url: BASE_URL + '/habbocreator', type: 'post', data: formData, dataType: 'json', processData: false, contentType: false }).always(function(response) { callback(response); }); }, }, loading: { show: function() { $("#loading-gif").fadeIn(); $("#loading-gif").find('.progress-bar').width('0%'); }, hide: function() { $("#loading-gif").fadeOut(); }, setProgress: function(percent) { $("#loading-gif").find('.progress-bar').animate({width: percent + '%'}, 10); } }, ui: { updateCount: function() { $("#keyframe-count").html('(' + keyframes.items.length + ')'); }, updateItems: function() { if(keyframes.items.length == 0) { $("#keyframes-items").html('You have not added any keyframes. Click "Add keyframe".'); return; } var template = $("#keyframe-template").html(); var output = ""; for(i in keyframes.items) { var item = keyframes.items[i]; item.index = i; item.id = (parseInt(i) + 1); item.keyframe = JSON.stringify(item); output += Mustache.render(template, item); } $("#keyframes-items").html(output); } } }; function getGifInstance() { return new GIF({ workers: 2, workerScript: BASE_URL + '/libs/gifjs/dist/gif.worker.js', quality: 10, width: 64, height: 110, transparent: '#000', }); } function downloadKeyframeURL(keyframe, callback) { return $.ajax({ url: BASE_URL + '/habbocreator', type: 'post', data: { url: keyframe.url, getUrl: 1, }, dataType: 'json' }).always(function(response) { callback(response.url, keyframe) }); } function createCanvasOfImage(img, callback) { var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); return canvas; }