diff --git a/src/pages/index.astro b/src/pages/index.astro
index 3eace07..79e1c23 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -223,14 +223,14 @@ import Tooltip from "../components/Tooltip.astro";
diff --git a/src/scripts/ascii-controller.ts b/src/scripts/ascii-controller.ts
index b948d21..59e42e6 100644
--- a/src/scripts/ascii-controller.ts
+++ b/src/scripts/ascii-controller.ts
@@ -417,11 +417,27 @@ export class AsciiController {
// ============= Export =============
savePNG(): void {
+ const wasShowing = this.zoomState.showMagnifier;
+
+ // 1. Force hide magnifier for clean export
+ if (wasShowing) {
+ this.zoomState.showMagnifier = false;
+ this.requestRender('uniforms');
+ // Force synchronous render
+ this.renderFrame();
+ }
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
AsciiExporter.downloadPNG(this.canvas, `ascii-art-${timestamp}.png`);
+
+ // 2. Restore state
+ if (wasShowing) {
+ this.zoomState.showMagnifier = true;
+ this.requestRender('uniforms');
+ }
}
- async copyText(): Promise {
+ saveText(): void {
if (!this.cachedGrid.imgEl) return;
const text = AsciiExporter.generateText(
this.cachedGrid.imgEl,
@@ -429,10 +445,11 @@ export class AsciiController {
this.cachedGrid.widthCols,
Math.floor(this.cachedGrid.heightRows)
);
- await AsciiExporter.copyToClipboard(text);
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
+ AsciiExporter.downloadText(text, `ascii-art-${timestamp}.txt`);
}
- async copyHTML(): Promise {
+ saveHTML(): void {
if (!this.cachedGrid.imgEl) return;
const html = AsciiExporter.generateHTML(
this.cachedGrid.imgEl,
@@ -440,7 +457,8 @@ export class AsciiController {
this.cachedGrid.widthCols,
Math.floor(this.cachedGrid.heightRows)
);
- await AsciiExporter.copyToClipboard(html);
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
+ AsciiExporter.downloadText(html, `ascii-art-${timestamp}.html`);
}
// ============= Utilities =============
diff --git a/src/scripts/ascii-exporter.ts b/src/scripts/ascii-exporter.ts
index f3a66de..5817675 100644
--- a/src/scripts/ascii-exporter.ts
+++ b/src/scripts/ascii-exporter.ts
@@ -8,6 +8,15 @@ export class AsciiExporter {
link.click();
}
+ static downloadText(content: string, filename: string) {
+ const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
+ const link = document.createElement('a');
+ link.href = URL.createObjectURL(blob);
+ link.download = filename;
+ link.click();
+ URL.revokeObjectURL(link.href);
+ }
+
static async copyToClipboard(text: string): Promise {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text);
diff --git a/src/scripts/ui-bindings.ts b/src/scripts/ui-bindings.ts
index 6956c5b..cc9bee9 100644
--- a/src/scripts/ui-bindings.ts
+++ b/src/scripts/ui-bindings.ts
@@ -308,9 +308,9 @@ export class UIBindings {
const btnCopyText = document.getElementById('btn-copy-text');
if (btnCopyText) {
- const handler = async (e: Event) => {
+ const handler = (e: Event) => {
e.stopPropagation();
- await this.controller.copyText();
+ this.controller.saveText();
};
this.buttonHandlers.set('btn-copy-text', handler);
btnCopyText.addEventListener('click', handler);
@@ -318,9 +318,9 @@ export class UIBindings {
const btnCopyHtml = document.getElementById('btn-copy-html');
if (btnCopyHtml) {
- const handler = async (e: Event) => {
+ const handler = (e: Event) => {
e.stopPropagation();
- await this.controller.copyHTML();
+ this.controller.saveHTML();
};
this.buttonHandlers.set('btn-copy-html', handler);
btnCopyHtml.addEventListener('click', handler);
diff --git a/src/scripts/webgl-ascii.ts b/src/scripts/webgl-ascii.ts
index a231139..ccaa5b0 100644
--- a/src/scripts/webgl-ascii.ts
+++ b/src/scripts/webgl-ascii.ts
@@ -46,7 +46,7 @@ export class WebGLAsciiRenderer {
private lastImage: HTMLImageElement | null;
constructor(_canvas: HTMLCanvasElement) {
- const gl = _canvas.getContext('webgl', { antialias: false });
+ const gl = _canvas.getContext('webgl', { antialias: false, preserveDrawingBuffer: true });
if (!gl) {
throw new Error('WebGL not supported');
}