mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Fix : Export to GIF : download option
In the GIF export panel, user can now choose between : - export online (previous 'upload' feature) - download GIF Labels have been updated in the PNG export panel to follow the same convention. CanvasToBlob library was modified and moved to dedicated utils to handle not only canvas, but also any base64 dateURI.
This commit is contained in:
parent
d501129e8e
commit
2809a551d7
117
src/js/app.js
117
src/js/app.js
@ -19,7 +19,10 @@
|
|||||||
this.shortcutService = new pskl.service.keyboard.ShortcutService();
|
this.shortcutService = new pskl.service.keyboard.ShortcutService();
|
||||||
this.shortcutService.init();
|
this.shortcutService.init();
|
||||||
|
|
||||||
var size = this.readSizeFromURL_();
|
var size = {
|
||||||
|
height : Constants.DEFAULT.HEIGHT,
|
||||||
|
width : Constants.DEFAULT.WIDTH
|
||||||
|
};
|
||||||
|
|
||||||
var descriptor = new pskl.model.piskel.Descriptor('New Piskel', '');
|
var descriptor = new pskl.model.piskel.Descriptor('New Piskel', '');
|
||||||
var piskel = new pskl.model.Piskel(size.width, size.height, descriptor);
|
var piskel = new pskl.model.Piskel(size.width, size.height, descriptor);
|
||||||
@ -111,35 +114,27 @@
|
|||||||
|
|
||||||
this.initTooltips_();
|
this.initTooltips_();
|
||||||
|
|
||||||
if (this.isAppEngineVersion) {
|
var piskelData = this.getPiskelInitData_();
|
||||||
this.finishInitAppEngine_();
|
if (piskelData && piskelData.piskel) {
|
||||||
} else {
|
this.loadPiskel_(piskelData.piskel, piskelData.descriptor, piskelData.fps);
|
||||||
this.finishInitGithub_();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
finishInitGithub_ : function () {
|
loadPiskel_ : function (serializedPiskel, descriptor, fps) {
|
||||||
var framesheetId = this.readFramesheetIdFromURL_();
|
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) {
|
||||||
if (framesheetId) {
|
piskel.setDescriptor(descriptor);
|
||||||
$.publish(Events.SHOW_NOTIFICATION, [{
|
|
||||||
"content" : "Loading animation with id : [" + framesheetId + "]"
|
|
||||||
}]);
|
|
||||||
this.loadFramesheetFromService(framesheetId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
finishInitAppEngine_ : function () {
|
|
||||||
if (pskl.appEnginePiskelData_ && pskl.appEnginePiskelData_.piskel) {
|
|
||||||
pskl.utils.serialization.Deserializer.deserialize(pskl.appEnginePiskelData_.piskel, function (piskel) {
|
|
||||||
piskel.setDescriptor(pskl.appEnginePiskelData_.descriptor);
|
|
||||||
pskl.app.piskelController.setPiskel(piskel);
|
pskl.app.piskelController.setPiskel(piskel);
|
||||||
pskl.app.animationController.setFPS(pskl.appEnginePiskelData_.fps);
|
pskl.app.animationController.setFPS(fps);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
getPiskelInitData_ : function () {
|
||||||
|
return pskl.appEnginePiskelData_;
|
||||||
},
|
},
|
||||||
|
|
||||||
isLoggedIn : function () {
|
isLoggedIn : function () {
|
||||||
return pskl.appEnginePiskelData_ && pskl.appEnginePiskelData_.isLoggedIn;
|
var piskelData = this.getPiskelInitData_();
|
||||||
|
return piskelData && piskelData.isLoggedIn;
|
||||||
},
|
},
|
||||||
|
|
||||||
initTooltips_ : function () {
|
initTooltips_ : function () {
|
||||||
@ -154,69 +149,6 @@
|
|||||||
this.previewFilmController.render(delta);
|
this.previewFilmController.render(delta);
|
||||||
},
|
},
|
||||||
|
|
||||||
readSizeFromURL_ : function () {
|
|
||||||
var sizeParam = this.readUrlParameter_("size");
|
|
||||||
var size;
|
|
||||||
// parameter expected as size=64x48 => size=widthxheight
|
|
||||||
var parts = sizeParam.split("x");
|
|
||||||
if (parts && parts.length == 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
|
|
||||||
var width = parseInt(parts[0], 10),
|
|
||||||
height = parseInt(parts[1], 10);
|
|
||||||
|
|
||||||
size = {
|
|
||||||
height : Math.min(height, Constants.MAX_HEIGHT),
|
|
||||||
width : Math.min(width, Constants.MAX_WIDTH)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
size = {
|
|
||||||
height : Constants.DEFAULT.HEIGHT,
|
|
||||||
width : Constants.DEFAULT.WIDTH
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
},
|
|
||||||
|
|
||||||
readFramesheetIdFromURL_ : function () {
|
|
||||||
return this.readUrlParameter_("frameId");
|
|
||||||
},
|
|
||||||
|
|
||||||
readUrlParameter_ : function (paramName) {
|
|
||||||
var searchString = window.location.search.substring(1);
|
|
||||||
var params = searchString.split("&");
|
|
||||||
for (var i = 0; i < params.length; i++) {
|
|
||||||
var param = params[i].split("=");
|
|
||||||
if (param[0] == paramName) {
|
|
||||||
return window.unescape(param[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
},
|
|
||||||
|
|
||||||
loadFramesheetFromService : function (frameId) {
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', Constants.STATIC.URL.GET + '?l=' + frameId, true);
|
|
||||||
xhr.responseType = 'text';
|
|
||||||
xhr.onload = function (e) {
|
|
||||||
var res = JSON.parse(this.responseText);
|
|
||||||
pskl.utils.serialization.Deserializer.deserialize(res.framesheet, function (piskel) {
|
|
||||||
pskl.app.piskelController.setPiskel(piskel);
|
|
||||||
pskl.app.animationController.setFPS(res.fps);
|
|
||||||
|
|
||||||
$.publish(Events.HIDE_NOTIFICATION);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.onerror = function () {
|
|
||||||
$.publish(Events.HIDE_NOTIFICATION);
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
},
|
|
||||||
|
|
||||||
store : function (callbacks) {
|
|
||||||
this.storageService.store(callbacks);
|
|
||||||
},
|
|
||||||
|
|
||||||
getFirstFrameAsPng : function () {
|
getFirstFrameAsPng : function () {
|
||||||
var firstFrame = this.piskelController.getFrameAt(0);
|
var firstFrame = this.piskelController.getFrameAt(0);
|
||||||
var canvasRenderer = new pskl.rendering.CanvasRenderer(firstFrame, 1);
|
var canvasRenderer = new pskl.rendering.CanvasRenderer(firstFrame, 1);
|
||||||
@ -229,21 +161,6 @@
|
|||||||
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
||||||
var framesheetCanvas = renderer.renderAsCanvas();
|
var framesheetCanvas = renderer.renderAsCanvas();
|
||||||
return framesheetCanvas.toDataURL("image/png");
|
return framesheetCanvas.toDataURL("image/png");
|
||||||
},
|
|
||||||
|
|
||||||
uploadAsSpritesheetPNG : function () {
|
|
||||||
var imageData = this.getFramesheetAsPng();
|
|
||||||
this.imageUploadService.upload(imageData, this.openWindow.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
openWindow : function (url) {
|
|
||||||
var options = [
|
|
||||||
"dialog=yes", "scrollbars=no", "status=no",
|
|
||||||
"width=" + this.piskelController.getWidth() * this.piskelController.getFrameCount(),
|
|
||||||
"height=" + this.piskelController.getHeight()
|
|
||||||
].join(",");
|
|
||||||
|
|
||||||
window.open(url, "piskel-export", options);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -34,8 +34,13 @@
|
|||||||
this.previewContainerEl = document.querySelector(".gif-export-preview");
|
this.previewContainerEl = document.querySelector(".gif-export-preview");
|
||||||
this.radioGroupEl = document.querySelector(".gif-export-radio-group");
|
this.radioGroupEl = document.querySelector(".gif-export-radio-group");
|
||||||
|
|
||||||
this.uploadForm = $("[name=gif-export-upload-form]");
|
this.uploadButton = $(".gif-upload-button");
|
||||||
this.uploadForm.submit(this.onUploadFormSubmit_.bind(this));
|
this.uploadButton.click(this.onUploadButtonClick_.bind(this));
|
||||||
|
|
||||||
|
this.downloadButton = $(".gif-download-button");
|
||||||
|
this.downloadButton.click(this.onDownloadButtonClick_.bind(this));
|
||||||
|
|
||||||
|
this.exportForm = $(".gif-export-form");
|
||||||
|
|
||||||
this.exportProgressStatusEl = document.querySelector('.gif-export-progress-status');
|
this.exportProgressStatusEl = document.querySelector('.gif-export-progress-status');
|
||||||
this.exportProgressBarEl = document.querySelector('.gif-export-progress-bar');
|
this.exportProgressBarEl = document.querySelector('.gif-export-progress-bar');
|
||||||
@ -43,15 +48,27 @@
|
|||||||
this.createRadioElements_();
|
this.createRadioElements_();
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.GifExportController.prototype.onUploadFormSubmit_ = function (evt) {
|
ns.GifExportController.prototype.onUploadButtonClick_ = function (evt) {
|
||||||
evt.originalEvent.preventDefault();
|
evt.originalEvent.preventDefault();
|
||||||
var selectedZoom = this.getSelectedZoom_(),
|
var zoom = this.getSelectedZoom_(),
|
||||||
fps = this.piskelController.getFPS(),
|
fps = this.piskelController.getFPS();
|
||||||
zoom = selectedZoom;
|
|
||||||
|
|
||||||
this.renderAsImageDataAnimatedGIF(zoom, fps, this.onGifRenderingCompleted_.bind(this));
|
this.renderAsImageDataAnimatedGIF(zoom, fps, this.onGifRenderingCompleted_.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.GifExportController.prototype.onDownloadButtonClick_ = function (evt) {
|
||||||
|
var fileName = this.piskelController.getPiskel().getDescriptor().name + '.gif';
|
||||||
|
var zoom = this.getSelectedZoom_(),
|
||||||
|
fps = this.piskelController.getFPS();
|
||||||
|
|
||||||
|
this.renderAsImageDataAnimatedGIF(zoom, fps, function (imageData) {
|
||||||
|
pskl.app.imageUploadService.upload(imageData, this.onImageUploadCompleted_.bind(this));
|
||||||
|
pskl.utils.ImageToBlob.imageDataToBlob(imageData, "image/gif", function(blob) {
|
||||||
|
pskl.utils.FileUtils.downloadAsFile(fileName, blob);
|
||||||
|
});
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
ns.GifExportController.prototype.onGifRenderingCompleted_ = function (imageData) {
|
ns.GifExportController.prototype.onGifRenderingCompleted_ = function (imageData) {
|
||||||
this.updatePreview_(imageData);
|
this.updatePreview_(imageData);
|
||||||
this.previewContainerEl.classList.add("preview-upload-ongoing");
|
this.previewContainerEl.classList.add("preview-upload-ongoing");
|
||||||
@ -62,7 +79,6 @@
|
|||||||
this.updatePreview_(imageUrl);
|
this.updatePreview_(imageUrl);
|
||||||
this.updateStatus_(imageUrl);
|
this.updateStatus_(imageUrl);
|
||||||
this.previewContainerEl.classList.remove("preview-upload-ongoing");
|
this.previewContainerEl.classList.remove("preview-upload-ongoing");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.GifExportController.prototype.updatePreview_ = function (src) {
|
ns.GifExportController.prototype.updatePreview_ = function (src) {
|
||||||
@ -70,7 +86,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.GifExportController.prototype.getSelectedZoom_ = function () {
|
ns.GifExportController.prototype.getSelectedZoom_ = function () {
|
||||||
var radiosColl = this.uploadForm.get(0).querySelectorAll("[name=gif-zoom-level]"),
|
var radiosColl = this.exportForm.get(0).querySelectorAll("[name=gif-zoom-level]"),
|
||||||
radios = Array.prototype.slice.call(radiosColl,0);
|
radios = Array.prototype.slice.call(radiosColl,0);
|
||||||
var selectedRadios = radios.filter(function(radio) {return !!radio.checked;});
|
var selectedRadios = radios.filter(function(radio) {return !!radio.checked;});
|
||||||
|
|
||||||
@ -105,15 +121,6 @@
|
|||||||
return radioEl;
|
return radioEl;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.GifExportController.prototype.blobToBase64_ = function(blob, cb) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onload = function() {
|
|
||||||
var dataUrl = reader.result;
|
|
||||||
cb(dataUrl);
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(blob);
|
|
||||||
};
|
|
||||||
|
|
||||||
ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(zoom, fps, cb) {
|
ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(zoom, fps, cb) {
|
||||||
var colorCount = pskl.app.currentColorsService.getCurrentColors().length;
|
var colorCount = pskl.app.currentColorsService.getCurrentColors().length;
|
||||||
var preserveColors = colorCount < MAX_GIF_COLORS;
|
var preserveColors = colorCount < MAX_GIF_COLORS;
|
||||||
@ -140,7 +147,7 @@
|
|||||||
|
|
||||||
gif.on('finished', function(blob) {
|
gif.on('finished', function(blob) {
|
||||||
this.hideProgressStatus_();
|
this.hideProgressStatus_();
|
||||||
this.blobToBase64_(blob, cb);
|
pskl.utils.FileUtils.readFile(blob, cb);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
gif.render();
|
gif.render();
|
||||||
|
@ -16,21 +16,19 @@
|
|||||||
|
|
||||||
document.querySelector(".zip-generate-button").addEventListener('click', this.onZipButtonClick_.bind(this));
|
document.querySelector(".zip-generate-button").addEventListener('click', this.onZipButtonClick_.bind(this));
|
||||||
|
|
||||||
this.updatePreview_(this.getFramesheetAsBase64Png());
|
this.setPreviewSrc_(this.getFramesheetAsCanvas().toDataURL("image/png"));
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.onPngDownloadButtonClick_ = function (evt) {
|
ns.PngExportController.prototype.onPngDownloadButtonClick_ = function (evt) {
|
||||||
var fileName = this.getPiskelName_() + '.png';
|
var fileName = this.getPiskelName_() + '.png';
|
||||||
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
pskl.utils.ImageToBlob.canvasToBlob(this.getFramesheetAsCanvas(), function(blob) {
|
||||||
var canvas = renderer.renderAsCanvas();
|
|
||||||
canvas.toBlob(function(blob) {
|
|
||||||
pskl.utils.FileUtils.downloadAsFile(fileName, blob);
|
pskl.utils.FileUtils.downloadAsFile(fileName, blob);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.onPngUploadButtonClick_ = function (evt) {
|
ns.PngExportController.prototype.onPngUploadButtonClick_ = function (evt) {
|
||||||
this.previewContainerEl.classList.add("preview-upload-ongoing");
|
this.previewContainerEl.classList.add("preview-upload-ongoing");
|
||||||
pskl.app.imageUploadService.upload(this.getFramesheetAsBase64Png(), this.onImageUploadCompleted_.bind(this));
|
pskl.app.imageUploadService.upload(this.getFramesheetAsCanvas().toDataURL("image/png"), this.onImageUploadCompleted_.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.onZipButtonClick_ = function () {
|
ns.PngExportController.prototype.onZipButtonClick_ = function () {
|
||||||
@ -59,10 +57,9 @@
|
|||||||
return this.piskelController.getPiskel().getDescriptor().name;
|
return this.piskelController.getPiskel().getDescriptor().name;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.getFramesheetAsBase64Png = function () {
|
ns.PngExportController.prototype.getFramesheetAsCanvas = function () {
|
||||||
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
||||||
var framesheetCanvas = renderer.renderAsCanvas();
|
return renderer.renderAsCanvas();
|
||||||
return framesheetCanvas.toDataURL("image/png");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.onImageUploadCompleted_ = function (imageUrl) {
|
ns.PngExportController.prototype.onImageUploadCompleted_ = function (imageUrl) {
|
||||||
@ -84,7 +81,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.updatePreview_ = function (src) {
|
ns.PngExportController.prototype.setPreviewSrc_ = function (src) {
|
||||||
this.previewContainerEl.innerHTML = "<img class='light-picker-background' style='max-width:240px;' src='"+src+"'/>";
|
this.previewContainerEl.innerHTML = "<img class='light-picker-background' style='max-width:240px;' src='"+src+"'/>";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
this.piskelController.getPiskel().setDescriptor(descriptor);
|
this.piskelController.getPiskel().setDescriptor(descriptor);
|
||||||
|
|
||||||
this.beforeSaving_();
|
this.beforeSaving_();
|
||||||
pskl.app.store({
|
pskl.app.storageService.store({
|
||||||
success : this.onSaveSuccess_.bind(this),
|
success : this.onSaveSuccess_.bind(this),
|
||||||
error : this.onSaveError_.bind(this),
|
error : this.onSaveError_.bind(this),
|
||||||
after : this.afterSaving_.bind(this)
|
after : this.afterSaving_.bind(this)
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
/* canvas-toBlob.js
|
|
||||||
* A canvas.toBlob() implementation.
|
|
||||||
* 2011-07-13
|
|
||||||
*
|
|
||||||
* By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
|
|
||||||
* License: X11/MIT
|
|
||||||
* See LICENSE.md
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*global self */
|
|
||||||
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
|
||||||
plusplus: true */
|
|
||||||
|
|
||||||
/*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */
|
|
||||||
|
|
||||||
(function(view) {
|
|
||||||
"use strict";
|
|
||||||
var
|
|
||||||
Uint8Array = view.Uint8Array
|
|
||||||
, HTMLCanvasElement = view.HTMLCanvasElement
|
|
||||||
, is_base64_regex = /\s*;\s*base64\s*(?:;|$)/i
|
|
||||||
, base64_ranks
|
|
||||||
, decode_base64 = function(base64) {
|
|
||||||
var
|
|
||||||
len = base64.length
|
|
||||||
, buffer = new Uint8Array(len / 4 * 3 | 0)
|
|
||||||
, i = 0
|
|
||||||
, outptr = 0
|
|
||||||
, last = [0, 0]
|
|
||||||
, state = 0
|
|
||||||
, save = 0
|
|
||||||
, rank
|
|
||||||
, code
|
|
||||||
, undef
|
|
||||||
;
|
|
||||||
while (len--) {
|
|
||||||
code = base64.charCodeAt(i++);
|
|
||||||
rank = base64_ranks[code-43];
|
|
||||||
if (rank !== 255 && rank !== undef) {
|
|
||||||
last[1] = last[0];
|
|
||||||
last[0] = code;
|
|
||||||
save = (save << 6) | rank;
|
|
||||||
state++;
|
|
||||||
if (state === 4) {
|
|
||||||
buffer[outptr++] = save >>> 16;
|
|
||||||
if (last[1] !== 61 /* padding character */) {
|
|
||||||
buffer[outptr++] = save >>> 8;
|
|
||||||
}
|
|
||||||
if (last[0] !== 61 /* padding character */) {
|
|
||||||
buffer[outptr++] = save;
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 2/3 chance there's going to be some null bytes at the end, but that
|
|
||||||
// doesn't really matter with most image formats.
|
|
||||||
// If it somehow matters for you, truncate the buffer up outptr.
|
|
||||||
return buffer.buffer;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
if (Uint8Array) {
|
|
||||||
base64_ranks = new Uint8Array([
|
|
||||||
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1
|
|
||||||
, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
|
||||||
, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
|
|
||||||
, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
|
|
||||||
, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if (HTMLCanvasElement && !HTMLCanvasElement.prototype.toBlob) {
|
|
||||||
HTMLCanvasElement.prototype.toBlob = function(callback, type /*, ...args*/) {
|
|
||||||
if (!type) {
|
|
||||||
type = "image/png";
|
|
||||||
} if (this.mozGetAsFile) {
|
|
||||||
callback(this.mozGetAsFile("canvas", type));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var
|
|
||||||
args = Array.prototype.slice.call(arguments, 1)
|
|
||||||
, dataURI = this.toDataURL.apply(this, args)
|
|
||||||
, header_end = dataURI.indexOf(",")
|
|
||||||
, data = dataURI.substring(header_end + 1)
|
|
||||||
, is_base64 = is_base64_regex.test(dataURI.substring(0, header_end))
|
|
||||||
, blob
|
|
||||||
;
|
|
||||||
if (Blob.fake) {
|
|
||||||
// no reason to decode a data: URI that's just going to become a data URI again
|
|
||||||
blob = new Blob
|
|
||||||
if (is_base64) {
|
|
||||||
blob.encoding = "base64";
|
|
||||||
} else {
|
|
||||||
blob.encoding = "URI";
|
|
||||||
}
|
|
||||||
blob.data = data;
|
|
||||||
blob.size = data.length;
|
|
||||||
} else if (Uint8Array) {
|
|
||||||
if (is_base64) {
|
|
||||||
blob = new Blob([decode_base64(data)], {type: type});
|
|
||||||
} else {
|
|
||||||
blob = new Blob([decodeURIComponent(data)], {type: type});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(blob);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}(self));
|
|
@ -8,24 +8,6 @@
|
|||||||
ns.GithubStorageService.prototype.init = function () {};
|
ns.GithubStorageService.prototype.init = function () {};
|
||||||
|
|
||||||
ns.GithubStorageService.prototype.store = function (callbacks) {
|
ns.GithubStorageService.prototype.store = function (callbacks) {
|
||||||
var xhr = new XMLHttpRequest();
|
throw "Github save is no longer available. Use local save instead";
|
||||||
var formData = new FormData();
|
|
||||||
formData.append('framesheet_content', this.piskelController.serialize());
|
|
||||||
formData.append('fps_speed', this.piskelController.getFPS());
|
|
||||||
|
|
||||||
xhr.open('POST', Constants.STATIC.URL.SAVE, true);
|
|
||||||
|
|
||||||
xhr.onload = function(e) {
|
|
||||||
if (this.status == 200) {
|
|
||||||
var baseUrl = window.location.href.replace(window.location.search, "");
|
|
||||||
window.location.href = baseUrl + "?frameId=" + this.responseText;
|
|
||||||
} else {
|
|
||||||
this.onerror(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.onerror = function(e) {
|
|
||||||
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+this.status+")"}]);
|
|
||||||
};
|
|
||||||
xhr.send(formData);
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
51
src/js/utils/Base64.js
Normal file
51
src/js/utils/Base64.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
(function () {
|
||||||
|
var ns = $.namespace('pskl.utils');
|
||||||
|
|
||||||
|
var base64_ranks;
|
||||||
|
if (Uint8Array) {
|
||||||
|
base64_ranks = new Uint8Array([
|
||||||
|
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1,
|
||||||
|
-1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
|
||||||
|
-1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||||
|
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ns.Base64 = {
|
||||||
|
decode : function(base64) {
|
||||||
|
var outptr = 0;
|
||||||
|
var last = [0, 0];
|
||||||
|
var state = 0;
|
||||||
|
var save = 0;
|
||||||
|
|
||||||
|
var undef;
|
||||||
|
var len = base64.length, i = 0;
|
||||||
|
var buffer = new Uint8Array(len / 4 * 3 | 0);
|
||||||
|
while (len--) {
|
||||||
|
var code = base64.charCodeAt(i++);
|
||||||
|
var rank = base64_ranks[code-43];
|
||||||
|
if (rank !== 255 && rank !== undef) {
|
||||||
|
last[1] = last[0];
|
||||||
|
last[0] = code;
|
||||||
|
save = (save << 6) | rank;
|
||||||
|
state++;
|
||||||
|
if (state === 4) {
|
||||||
|
buffer[outptr++] = save >>> 16;
|
||||||
|
if (last[1] !== 61 /* padding character */) {
|
||||||
|
buffer[outptr++] = save >>> 8;
|
||||||
|
}
|
||||||
|
if (last[0] !== 61 /* padding character */) {
|
||||||
|
buffer[outptr++] = save;
|
||||||
|
}
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2/3 chance there's going to be some null bytes at the end, but that
|
||||||
|
// doesn't really matter with most image formats.
|
||||||
|
// If it somehow matters for you, truncate the buffer up outptr.
|
||||||
|
return buffer.buffer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
38
src/js/utils/ImageToBlob.js
Normal file
38
src/js/utils/ImageToBlob.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
(function () {
|
||||||
|
var ns = $.namespace('pskl.utils');
|
||||||
|
|
||||||
|
var BASE64_REGEX = /\s*;\s*base64\s*(?:;|$)/i;
|
||||||
|
|
||||||
|
ns.ImageToBlob = {
|
||||||
|
imageDataToBlob : function(dataURI, type, callback) {
|
||||||
|
var header_end = dataURI.indexOf(","),
|
||||||
|
data = dataURI.substring(header_end + 1),
|
||||||
|
isBase64 = BASE64_REGEX.test(dataURI.substring(0, header_end)),
|
||||||
|
blob;
|
||||||
|
|
||||||
|
if (Blob.fake) {
|
||||||
|
// no reason to decode a data: URI that's just going to become a data URI again
|
||||||
|
blob = new Blob();
|
||||||
|
blob.encoding = isBase64 ? "base64" : "URI";
|
||||||
|
blob.data = data;
|
||||||
|
blob.size = data.length;
|
||||||
|
} else if (Uint8Array) {
|
||||||
|
var blobData = isBase64 ? pskl.utils.Base64.decode(data) : decodeURIComponent(data);
|
||||||
|
blob = new Blob([blobData], {type: type});
|
||||||
|
}
|
||||||
|
callback(blob);
|
||||||
|
},
|
||||||
|
|
||||||
|
canvasToBlob : function(canvas, callback, type /*, ...args*/) {
|
||||||
|
type = type || "image/png";
|
||||||
|
|
||||||
|
if (this.mozGetAsFile) {
|
||||||
|
callback(this.mozGetAsFile("canvas", type));
|
||||||
|
} else {
|
||||||
|
var args = Array.prototype.slice.call(arguments, 2);
|
||||||
|
var dataURI = this.toDataURL.apply(this, args);
|
||||||
|
pskl.utils.ImageToBlob.imageDataToBlob(dataURI, type, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
// JSZip https://github.com/Stuk/jszip
|
// JSZip https://github.com/Stuk/jszip
|
||||||
"js/lib/jszip/jszip.min.js",
|
"js/lib/jszip/jszip.min.js",
|
||||||
"js/lib/canvastoblob/canvasToBlob.js",
|
|
||||||
|
|
||||||
// Spectrum color-picker library
|
// Spectrum color-picker library
|
||||||
"js/lib/spectrum/spectrum.js",
|
"js/lib/spectrum/spectrum.js",
|
||||||
@ -24,12 +23,14 @@
|
|||||||
// Libraries
|
// Libraries
|
||||||
"js/utils/core.js",
|
"js/utils/core.js",
|
||||||
"js/utils/UserAgent.js",
|
"js/utils/UserAgent.js",
|
||||||
|
"js/utils/Base64.js",
|
||||||
"js/utils/CanvasUtils.js",
|
"js/utils/CanvasUtils.js",
|
||||||
"js/utils/Dom.js",
|
"js/utils/Dom.js",
|
||||||
"js/utils/Math.js",
|
"js/utils/Math.js",
|
||||||
"js/utils/FileUtils.js",
|
"js/utils/FileUtils.js",
|
||||||
"js/utils/FrameUtils.js",
|
"js/utils/FrameUtils.js",
|
||||||
"js/utils/LayerUtils.js",
|
"js/utils/LayerUtils.js",
|
||||||
|
"js/utils/ImageToBlob.js",
|
||||||
"js/utils/ImageResizer.js",
|
"js/utils/ImageResizer.js",
|
||||||
"js/utils/PixelUtils.js",
|
"js/utils/PixelUtils.js",
|
||||||
"js/utils/Template.js",
|
"js/utils/Template.js",
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
<option value="4">Enabled - 4px wide</option>
|
<option value="4">Enabled - 4px wide</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-item">
|
<!-- <div class="settings-item">
|
||||||
<label for="tiled-preview">Display tiled preview :</label>
|
<label for="tiled-preview">Display tiled preview :</label>
|
||||||
<input type="checkbox" value="1" id="tiled-preview" name="tiled-preview-checkbox"/>
|
<input type="checkbox" value="1" id="tiled-preview" name="tiled-preview-checkbox"/>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -3,17 +3,19 @@
|
|||||||
Export to Animated GIF
|
Export to Animated GIF
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
|
<form action="" method="POST" class="gif-export-form">
|
||||||
<label>Select resolution:</label>
|
<label>Select resolution:</label>
|
||||||
<form action="" method="POST" name="gif-export-upload-form">
|
|
||||||
<script type="text/template" id="gif-export-radio-template">
|
<script type="text/template" id="gif-export-radio-template">
|
||||||
<label style="display:block"><input type="radio" name="gif-zoom-level" value="{{value}}"/>
|
<label style="display:block"><input type="radio" name="gif-zoom-level" value="{{value}}"/>
|
||||||
{{label}}</label>
|
{{label}}</label>
|
||||||
</script>
|
</script>
|
||||||
<div class="gif-export-radio-group"></div>
|
<div class="gif-export-radio-group"></div>
|
||||||
<input type="submit" class="button button-primary gif-upload-button" value="Upload" />
|
|
||||||
|
<button type="button" class="button button-primary gif-download-button">Download GIF</button>
|
||||||
|
<button type="button" class="button button gif-upload-button">Export online</button>
|
||||||
|
</form>
|
||||||
<span class="gif-export-progress-status"></span>
|
<span class="gif-export-progress-status"></span>
|
||||||
<div class="gif-export-progress-bar"></div>
|
<div class="gif-export-progress-bar"></div>
|
||||||
</form>
|
|
||||||
<div class="gif-export-preview"></div>
|
<div class="gif-export-preview"></div>
|
||||||
<div class="gif-upload-status"></div>
|
<div class="gif-upload-status"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<span>Preview : </span>
|
<span>Preview : </span>
|
||||||
<div class="png-export-preview"></div>
|
<div class="png-export-preview"></div>
|
||||||
<div class="png-export-radio-group"></div>
|
<div class="png-export-radio-group"></div>
|
||||||
<input type="button" class="button button-primary png-download-button" value="Download PNG" />
|
<button type="button" class="button button-primary png-download-button">Download PNG</button>
|
||||||
<input type="button" class="button png-upload-button" value="Upload PNG" />
|
<button type="button" class="button png-upload-button">Export online</button>
|
||||||
<!-- <input type="button" class="button png-download-button" value="Download" /> -->
|
<!-- <input type="button" class="button png-download-button" value="Download" /> -->
|
||||||
<div class="png-upload-status"></div>
|
<div class="png-upload-status"></div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user