mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-10-27 08:40:39 +00:00
Pixel-art preview: one-click PNG / GIF download
The community-browser preview page for pixel-art designs now exposes a "⬇ Download PNG" (single-frame) or "⬇ Download GIF" (multi-frame, animated) button next to Use/Fork, Share, and Save JSON. Means viewers can grab the sprite asset without forking it into the editor first. Implementation reuses the existing exportPixelArtToPngBlob / exportPixelArtToGifBlob / pixelExportFilename helpers from the editor's full export menu, at the default 4× scale (matches the editor's _pixelExportOpts default). GIF carries the source design's fps + loop settings. Gated on mode === 'pixelart' && !lockedPremium — locked premium pixel-art designs only expose the button after unlock (the design data isn't available before then). Self-authored designs and any unlocked / free pixel-art design get the button regardless of who published it. Button shows "Preparing…" while encoding (matters for big multi-frame GIFs where encoding can take a second or two). Errors land as a toast.
This commit is contained in:
1 parent
4a5930fe29
commit
95a39cc077
1 file changed
+57
@@ -22252,6 +22252,63 @@
|
||||
actionsDiv.insertBefore(presentBtn, saveJsonBtn);
|
||||
}
|
||||
|
||||
// Pixel-art designs get a one-click Download button that emits
|
||||
// a PNG for single-frame designs and an animated GIF for
|
||||
// multi-frame ones. Reuses the same export blob helpers the
|
||||
// editor's full export menu uses, at the default 4× scale.
|
||||
// Locked premium pixel-art designs only show this after unlock
|
||||
// — the design data isn't available otherwise.
|
||||
if (mode === 'pixelart' && !lockedPremium) {
|
||||
const pa = p.pixelArt || {};
|
||||
const frameCount = Array.isArray(pa.frames) ? pa.frames.length : 0;
|
||||
const isAnimated = frameCount > 1;
|
||||
const dlBtn = document.createElement('button');
|
||||
dlBtn.type = 'button';
|
||||
dlBtn.textContent = isAnimated ? '⬇ Download GIF' : '⬇ Download PNG';
|
||||
dlBtn.title = isAnimated
|
||||
? `Download as animated GIF (${frameCount} frames, ${pa.fps || 8} fps) at 4× scale`
|
||||
: 'Download as PNG at 4× scale';
|
||||
dlBtn.addEventListener('click', async (e) => {
|
||||
e.stopPropagation();
|
||||
const originalLabel = dlBtn.textContent;
|
||||
dlBtn.disabled = true;
|
||||
dlBtn.textContent = 'Preparing…';
|
||||
try {
|
||||
let blob;
|
||||
if (isAnimated) {
|
||||
blob = exportPixelArtToGifBlob(pa, {
|
||||
scale: 4,
|
||||
fps: pa.fps || 8,
|
||||
loop: pa.loop !== false,
|
||||
});
|
||||
} else {
|
||||
blob = await exportPixelArtToPngBlob(pa, {
|
||||
scale: 4,
|
||||
transparent: true,
|
||||
includeGrid: false,
|
||||
});
|
||||
}
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = pixelExportFilename(pa, 4, false, isAnimated ? 'gif' : 'png');
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
||||
toastSuccess(isAnimated
|
||||
? `Downloaded GIF (${frameCount} frames)`
|
||||
: `Downloaded PNG (${pa.width || 0}×${pa.height || 0} px at 4×)`);
|
||||
} catch (err) {
|
||||
toastError(err?.message || 'Download failed.');
|
||||
} finally {
|
||||
dlBtn.disabled = false;
|
||||
dlBtn.textContent = originalLabel;
|
||||
}
|
||||
});
|
||||
actionsDiv.insertBefore(dlBtn, saveJsonBtn);
|
||||
}
|
||||
|
||||
if (isDiscDesign) {
|
||||
const import1Btn = document.createElement('button');
|
||||
import1Btn.type = 'button';
|
||||
|
||||
Reference in new issue
Block a user