This commit is contained in:
th committed 2026-04-19 22:32:06 +02:00
1 parent fcefd258eb
commit 6b6157d786
23 files changed
+1140 -237

No files matched your search

+8 -8
View File
@@ -324,11 +324,11 @@ export function generateExampleHtml(scene: Scene, options: ExportOptions = {}):
const sceneBoot = generateSceneScriptBody(scene, options)
const aspect = `${scene.canvas.width} / ${scene.canvas.height}`
return `<!doctype html>
<html lang="de">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Animatr — Beispiel</title>
<title>Animatr — Example</title>
<style>
:root { color-scheme: light dark; }
body {
@@ -383,26 +383,26 @@ export function generateExampleHtml(scene: Scene, options: ExportOptions = {}):
</head>
<body>
<h1>Animatr Export</h1>
<p>Runtime einmal laden, dann beliebig viele Szenen auf einer Seite.</p>
<p>Load the runtime once, then embed as many scenes on the page as you like.</p>
<!-- Runtime: einmal pro Seite -->
<!-- Runtime: once per page -->
<script>
${runtime}
</script>
<div class="stage">
<!-- Szene: pro Animation -->
<!-- Scene: one per animation -->
<script>
${sceneBoot}
</script>
</div>
<div class="usage">
<h2>Einbinden in eine eigene Seite</h2>
<pre>&lt;!-- einmal pro Seite --&gt;
<h2>Embed on your own page</h2>
<pre>&lt;!-- once per page --&gt;
&lt;script src="animatr-runtime.js"&gt;&lt;/script&gt;
&lt;!-- je Animation ein Container + Scene-Script --&gt;
&lt;!-- per animation: one container + scene script --&gt;
&lt;div style="width: 800px; height: 450px;"&gt;
&lt;script src="animation.js"&gt;&lt;/script&gt;
&lt;/div&gt;
+7 -7
View File
@@ -32,28 +32,28 @@ export function parseProject(text: string): Scene {
try {
data = JSON.parse(text)
} catch {
throw new ProjectFileError('Datei ist kein gültiges JSON.')
throw new ProjectFileError('File is not valid JSON.')
}
if (!data || typeof data !== 'object') {
throw new ProjectFileError('Datei ist leer oder kein Objekt.')
throw new ProjectFileError('File is empty or not an object.')
}
const obj = data as Record<string, unknown>
if (obj.magic !== MAGIC) {
throw new ProjectFileError('Keine Animatr-Projektdatei (magic fehlt).')
throw new ProjectFileError('Not an Animatr project file (magic missing).')
}
const scene = obj.scene
if (!scene || typeof scene !== 'object') {
throw new ProjectFileError('Projektdatei enthält keine Szene.')
throw new ProjectFileError('Project file has no scene.')
}
const s = scene as Record<string, unknown>
if (!s.canvas || typeof s.canvas !== 'object') {
throw new ProjectFileError('Szenendaten unvollständig: canvas fehlt.')
throw new ProjectFileError('Scene data incomplete: canvas missing.')
}
if (!Array.isArray(s.layers)) {
throw new ProjectFileError('Szenendaten unvollständig: layers fehlt.')
throw new ProjectFileError('Scene data incomplete: layers missing.')
}
if (!Array.isArray(s.assets)) {
throw new ProjectFileError('Szenendaten unvollständig: assets fehlt.')
throw new ProjectFileError('Scene data incomplete: assets missing.')
}
return scene as Scene
}
+1 -1
View File
@@ -98,7 +98,7 @@ export async function getStoredProject(id: string): Promise<StoredProject | null
function defaultName(): string {
const d = new Date()
return `Projekt ${d.toLocaleDateString()} ${d.toLocaleTimeString([], {
return `Project ${d.toLocaleDateString()} ${d.toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit',
})}`
+4 -4
View File
@@ -40,10 +40,10 @@ export async function renderOnServer(
})
if (!startRes.ok) {
const body = await startRes.text().catch(() => '')
throw new Error(`Server start fehlgeschlagen (${startRes.status}): ${body.slice(0, 200)}`)
throw new Error(`Server start failed (${startRes.status}): ${body.slice(0, 200)}`)
}
const { jobId } = (await startRes.json()) as { jobId: string }
if (!jobId) throw new Error('Server lieferte keine jobId')
if (!jobId) throw new Error('Server did not return a jobId')
const downloadUrl = await new Promise<string>((resolve, reject) => {
const es = new EventSource(`${baseUrl}/render/${jobId}/events`)
@@ -78,13 +78,13 @@ export async function renderOnServer(
opts.signal?.removeEventListener('abort', onAbort)
if (data.error) reject(new Error(data.error))
else if (data.url) resolve(`${baseUrl}${data.url}`)
else reject(new Error('Server meldete fertig ohne Download-URL'))
else reject(new Error('Server reported done without download URL'))
}
}
es.onerror = () => {
es.close()
opts.signal?.removeEventListener('abort', onAbort)
reject(new Error('Verbindung zum Render-Server verloren'))
reject(new Error('Connection to render server lost'))
}
})
+1 -1
View File
@@ -46,7 +46,7 @@ export async function renderSceneToVideo(
): Promise<VideoExportResult> {
const mimeType = pickMimeType()
if (!mimeType) {
throw new Error('MediaRecorder wird von diesem Browser nicht unterstützt.')
throw new Error('MediaRecorder is not supported by this browser.')
}
const canvas = document.createElement('canvas')