mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Feature : export to ZIP
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
// Piskel externs.
|
// Piskel externs.
|
||||||
var exports;
|
var exports;
|
||||||
|
var pskl_exports;
|
||||||
var $;
|
var $;
|
||||||
var console;
|
var console;
|
||||||
var pskl;
|
var pskl;
|
||||||
|
@@ -11,19 +11,54 @@
|
|||||||
this.previewContainerEl = document.querySelectorAll(".png-export-preview")[0];
|
this.previewContainerEl = document.querySelectorAll(".png-export-preview")[0];
|
||||||
this.uploadStatusContainerEl = document.querySelectorAll(".png-upload-status")[0];
|
this.uploadStatusContainerEl = document.querySelectorAll(".png-upload-status")[0];
|
||||||
|
|
||||||
this.uploadForm = $("[name=png-export-upload-form]");
|
document.querySelector(".png-upload-button").addEventListener('click', this.onPngUploadButtonClick_.bind(this));
|
||||||
this.uploadForm.submit(this.onUploadFormSubmit_.bind(this));
|
document.querySelector(".png-download-button").addEventListener('click', this.onPngDownloadButtonClick_.bind(this));
|
||||||
|
|
||||||
|
document.querySelector(".zip-generate-button").addEventListener('click', this.onZipButtonClick_.bind(this));
|
||||||
|
|
||||||
this.updatePreview_(this.getFramesheetAsBase64Png());
|
this.updatePreview_(this.getFramesheetAsBase64Png());
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.onUploadFormSubmit_ = function (evt) {
|
ns.PngExportController.prototype.onPngDownloadButtonClick_ = function (evt) {
|
||||||
evt.originalEvent.preventDefault();
|
var fileName = this.getPiskelName_() + '.png';
|
||||||
|
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
||||||
|
var canvas = renderer.renderAsCanvas();
|
||||||
|
canvas.toBlob(function(blob) {
|
||||||
|
pskl.utils.FileUtils.downloadAsFile(fileName, blob);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
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.getFramesheetAsBase64Png(), this.onImageUploadCompleted_.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.PngExportController.prototype.onZipButtonClick_ = function () {
|
||||||
|
var zip = new window.JSZip();
|
||||||
|
|
||||||
|
for (var i = 0; i < this.piskelController.getFrameCount(); i++) {
|
||||||
|
var frame = this.piskelController.getFrameAt(i);
|
||||||
|
var canvas = this.getFrameAsCanvas_(frame);
|
||||||
|
var filename = "sprite_" + (i+1) + ".png";
|
||||||
|
zip.file(filename, pskl.CanvasUtils.getBase64FromCanvas(canvas) + '\n', {base64: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileName = this.getPiskelName_() + '.zip';
|
||||||
|
|
||||||
|
var fileContent = zip.generate({type:"blob"});
|
||||||
|
pskl.utils.FileUtils.downloadAsFile(fileName, fileContent);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PngExportController.prototype.getFrameAsCanvas_ = function (frame) {
|
||||||
|
var canvasRenderer = new pskl.rendering.CanvasRenderer(frame, 1);
|
||||||
|
canvasRenderer.drawTransparentAs(Constants.TRANSPARENT_COLOR);
|
||||||
|
return canvasRenderer.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PngExportController.prototype.getPiskelName_ = function () {
|
||||||
|
return this.piskelController.piskel.getDescriptor().name;
|
||||||
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.getFramesheetAsBase64Png = function () {
|
ns.PngExportController.prototype.getFramesheetAsBase64Png = function () {
|
||||||
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
||||||
var framesheetCanvas = renderer.renderAsCanvas();
|
var framesheetCanvas = renderer.renderAsCanvas();
|
||||||
|
107
src/js/lib/canvastoblob/canvasToBlob.js
Normal file
107
src/js/lib/canvastoblob/canvasToBlob.js
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/* 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));
|
14
src/js/lib/jszip/jszip.min.js
vendored
Normal file
14
src/js/lib/jszip/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -44,6 +44,12 @@
|
|||||||
getImageDataFromCanvas : function (canvas) {
|
getImageDataFromCanvas : function (canvas) {
|
||||||
var sourceContext = canvas.getContext('2d');
|
var sourceContext = canvas.getContext('2d');
|
||||||
return sourceContext.getImageData(0, 0, canvas.width, canvas.height).data;
|
return sourceContext.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||||
|
},
|
||||||
|
|
||||||
|
getBase64FromCanvas : function (canvas, format) {
|
||||||
|
format = format || "png";
|
||||||
|
var data = canvas.toDataURL("image/" + format);
|
||||||
|
return data.substr(data.indexOf(',')+1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
@@ -8,6 +8,21 @@
|
|||||||
callback(event.target.result);
|
callback(event.target.result);
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
|
},
|
||||||
|
|
||||||
|
downloadAsFile : function (filename, content) {
|
||||||
|
var saveAs = window.saveAs || (navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator));
|
||||||
|
if (saveAs) {
|
||||||
|
saveAs(content, filename);
|
||||||
|
} else {
|
||||||
|
var downloadLink = document.createElement('a');
|
||||||
|
content = window.URL.createObjectURL(content);
|
||||||
|
downloadLink.setAttribute('href', content);
|
||||||
|
downloadLink.setAttribute('download', filename);
|
||||||
|
document.body.appendChild(downloadLink);
|
||||||
|
downloadLink.click();
|
||||||
|
document.body.removeChild(downloadLink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
@@ -6,7 +6,7 @@
|
|||||||
window.setTimeout(function () {loadingMask.parentNode.removeChild(loadingMask);}, 600)
|
window.setTimeout(function () {loadingMask.parentNode.removeChild(loadingMask);}, 600)
|
||||||
pskl.app.init();
|
pskl.app.init();
|
||||||
// cleanup
|
// cleanup
|
||||||
delete window.exports;
|
delete window.pskl_exports;
|
||||||
delete window.loadDebugScripts;
|
delete window.loadDebugScripts;
|
||||||
delete window.done;
|
delete window.done;
|
||||||
};
|
};
|
||||||
@@ -37,20 +37,20 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (window.location.href.indexOf("debug") != -1) {
|
if (window.location.href.indexOf("debug") != -1) {
|
||||||
window.exports = {};
|
window.pskl_exports = {};
|
||||||
var scriptIndex = 0;
|
var scriptIndex = 0;
|
||||||
window.loadNextScript = function () {
|
window.loadNextScript = function () {
|
||||||
if (scriptIndex == window.exports.scripts.length) {
|
if (scriptIndex == window.pskl_exports.scripts.length) {
|
||||||
window.onPiskelReady();
|
window.onPiskelReady();
|
||||||
} else {
|
} else {
|
||||||
loadScript(window.exports.scripts[scriptIndex], "loadNextScript()");
|
loadScript(window.pskl_exports.scripts[scriptIndex], "loadNextScript()");
|
||||||
scriptIndex ++;
|
scriptIndex ++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
loadScript("piskel-script-list.js", "loadNextScript()");
|
loadScript("piskel-script-list.js", "loadNextScript()");
|
||||||
|
|
||||||
window.loadStyles = function () {
|
window.loadStyles = function () {
|
||||||
var styles = window.exports.styles;
|
var styles = window.pskl_exports.styles;
|
||||||
for (var i = 0 ; i < styles.length ; i++) {
|
for (var i = 0 ; i < styles.length ; i++) {
|
||||||
loadStyle(styles[i]);
|
loadStyle(styles[i]);
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,17 @@
|
|||||||
// This list is used both by the grunt build and index.html (in debug mode)
|
// This list is used both by the grunt build and index.html (in debug mode)
|
||||||
|
|
||||||
exports.scripts = [
|
(typeof exports != "undefined" ? exports : pskl_exports).scripts = [
|
||||||
// Core libraries
|
// Core libraries
|
||||||
"js/lib/jquery-1.8.0.js","js/lib/jquery-ui-1.10.3.custom.js","js/lib/pubsub.js","js/lib/bootstrap/bootstrap.js",
|
"js/lib/jquery-1.8.0.js","js/lib/jquery-ui-1.10.3.custom.js","js/lib/pubsub.js","js/lib/bootstrap/bootstrap.js",
|
||||||
|
|
||||||
// GIF Encoding libraries
|
// GIF Encoding libraries
|
||||||
"js/lib/gif/gif.worker.js",
|
"js/lib/gif/gif.worker.js",
|
||||||
"js/lib/gif/gif.js",
|
"js/lib/gif/gif.js",
|
||||||
|
|
||||||
|
// JSZip https://github.com/Stuk/jszip
|
||||||
|
"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",
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// This list is used both by the grunt build and index.html (in debug mode)
|
// This list is used both by the grunt build and index.html (in debug mode)
|
||||||
|
|
||||||
exports.styles = [
|
(typeof exports != "undefined" ? exports : pskl_exports).styles = [
|
||||||
"css/reset.css",
|
"css/reset.css",
|
||||||
"css/style.css",
|
"css/style.css",
|
||||||
"css/forms.css",
|
"css/forms.css",
|
||||||
|
@@ -37,16 +37,16 @@
|
|||||||
<div
|
<div
|
||||||
data-setting="gif"
|
data-setting="gif"
|
||||||
class="tool-icon upload-cloud-icon"
|
class="tool-icon upload-cloud-icon"
|
||||||
title="Upload as an animated GIF"
|
title="Export Animation"
|
||||||
rel="tooltip" data-placement="left">
|
rel="tooltip" data-placement="left">
|
||||||
<span class="label">GIF</span>
|
<span class="label">ANIM</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-setting="png"
|
data-setting="png"
|
||||||
class="tool-icon upload-cloud-icon"
|
class="tool-icon upload-cloud-icon"
|
||||||
title="Upload as a spritesheet PNG"
|
title="Export Spritesheet"
|
||||||
rel="tooltip" data-placement="left">
|
rel="tooltip" data-placement="left">
|
||||||
<span class="label">PNG</span>
|
<span class="label">SHEET</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@@ -1,15 +1,23 @@
|
|||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<div class="settings-title">
|
<div class="settings-title">
|
||||||
Export to PNG
|
Export Spritesheet as PNG
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<span>Preview : </span>
|
<span>Preview : </span>
|
||||||
<div class="png-export-preview"></div>
|
<div class="png-export-preview"></div>
|
||||||
<form action="" method="POST" name="png-export-upload-form">
|
|
||||||
<div class="png-export-radio-group"></div>
|
<div class="png-export-radio-group"></div>
|
||||||
<input type="submit" class="button button-primary png-upload-button" value="Upload" />
|
<input type="button" class="button button-primary png-download-button" value="Download PNG" />
|
||||||
|
<input type="button" class="button png-upload-button" value="Upload PNG" />
|
||||||
<!-- <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>
|
||||||
</form>
|
</div>
|
||||||
|
<div class="settings-title">
|
||||||
|
Export Spritesheet as ZIP
|
||||||
|
</div>
|
||||||
|
<div class="settings-item">
|
||||||
|
<span>A ZIP archive will be created with one PNG file per frame.</span>
|
||||||
|
<div style="margin-top:10px;">
|
||||||
|
<button type="button" class="button button-primary zip-generate-button"/>Download ZIP</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
Reference in New Issue
Block a user