Kreativsimulator per <iframe> einbinden
Betten Sie den Kreativsimulator in Sekunden in Ihre eigene Website ein – und steuern Sie ihn optional komplett von außen: eigene Produktauswahl, eigene Motive, eigene UI. Dieser Leitfaden zeigt jeden Schritt mit kopierbarem Code und einer Live-Demo zum Ausprobieren.
Domains freischalten lassen
Aus Sicherheitsgründen erlaubt der Browser das Einbetten nur von Domains, die wir vorab freigeschaltet haben (Content-Security-Policy: frame-ancestors).
Teilen Sie uns vor der Einbettung alle Domains mit, auf denen der iframe erscheinen soll. Wir tragen sie in die Konfiguration Ihres Mandanten ein. Wildcards sind möglich.
Zum Beispiel:
https://www.ihre-agentur.dehttps://kampagne.ihre-agentur.dehttps://*.ihre-agentur.de (Wildcard)
Ohne Freischaltung bleibt der iframe leer (weiße Fläche). Auch die Live-Demo weiter unten lädt nur, wenn die einbettende Domain freigeschaltet ist – sonst nutzen Sie den „In neuem Tab öffnen“-Link.
Einbettungs-Code
Ein einziges <iframe>-Tag genügt. Kein API-Key, keine zusätzliche Konfiguration auf Ihrer Seite – die Authentifizierung läuft vollständig serverseitig.
Code ansehen HTML
<iframe
src="https://demo.kreativsimulator.com/"
title="Kreativsimulator"
style="width: 100%; height: 720px; border: 0;"
allow="fullscreen"
loading="lazy"
></iframe> Embed-URL: https://<dein-mandant>.kreativsimulator.com/
Der Mandant wird aus der Subdomain abgeleitet. Für die öffentliche Sandbox verwenden Sie demo.kreativsimulator.com.
Sprache und Start-Produkt lassen sich optional per Query-Parameter vorgeben – siehe nächster Abschnitt.
URL-Parameter
Optional lassen sich folgende Query-Parameter an die Embed-URL anhängen (mit ? beginnen, mit & verketten):
| Parameter | Werte | Wirkung | Default |
|---|---|---|---|
lang | de · en · fr · it | UI-Sprache | Mandant → Browser → de |
product | Produkt-Code (ec5472c2) | Lädt direkt dieses Produkt (Deep-Link). Unbekannter Code → erstes Produkt. | Erstes Produkt |
header | 0 · 1 | Kopfzeile (Logo + Produkt-Auswahl) aus-/einblenden | 1 (sichtbar) |
sidebar | 0 · 1 | Seitenleiste (inkl. Mobil-Drawer + Hamburger) aus-/einblenden | 1 (sichtbar) |
playback | 0 · 1 | Abspiel-/Transport-Knöpfe in der Leiste aus-/einblenden | 1 (sichtbar) |
timeline | 0 · 1 | Zeitleiste (Scrubbing-Balken) aus-/einblenden | 1 (sichtbar) |
export | 0 · 1 | „Kreation exportieren“-Button aus-/einblenden | 1 (sichtbar) |
effects | 0 · 1 | Effekt-Dropdown (nur Foto-Produkte) aus-/einblenden – z. B. für einen eigenen Picker | 1 (sichtbar) |
fullscreen | 0 · 1 | Vollbild-Icon: 0=nie, 1=immer (auch Desktop); ohne Param = nur mobil/im Vollbild | adaptiv |
embed | minimal · kiosk | Kurzform: blendet Header, Sidebar und Export aus (Abspielleiste bleibt) | – |
theme | URL zu einer CSS-Datei | Lädt ein eigenes Theme (CSS-Variablen), das das Mandanten-Theme überschreibt | – |
bg | beliebige CSS-Farbe, transparent oder Bild-URL | Hintergrund der Fläche um den Canvas (Letterbox/Rahmen), nicht das Video | Theme-Hintergrund |
stage | <Breite>x<Höhe> (1280x720) | Feste Anzeige-Pixelgröße des Canvas statt fluider Breite | fluid (100 %) |
placeholderBg | beliebige CSS-Farbe | Hintergrund der Platzhalter-Box (Loader ohne Motiv) – Direkt-Shortcut ohne ?theme=-Datei | Theme/Default (#ffffff) |
placeholderText | beliebige CSS-Farbe | Farbe des Buchstabens in der Platzhalter-Box | Theme/Default (#000000) |
placeholderBorder | beliebige CSS-Farbe | Rahmenfarbe der Platzhalter-Box | Theme/Default (#000000) |
- Boolean-Parameter akzeptieren
0/1(auchtrue/false,yes/no).embed=kioskwird zuerst ausgewertet – einzelne Parameter überschreiben es danach (z. B. zeigt?embed=kiosk&header=1trotzdem die Kopfzeile). - Die Sichtbarkeits-Schalter (
header/sidebar/playback/timeline/export/effects) lassen sich auch zur Laufzeit persetChromeumschalten (siehe API). Wiedergabe, Export und Effekt-Auswahl funktionieren immer per postMessage – unabhängig davon, ob die zugehörigen Bedienelemente sichtbar sind. So bauen Sie eine komplett eigene Bedienung (eigener Effekt-Picker viasetEffect, eingebauten Dropdown miteffects=0ausblenden). - theme-CSS: wird als zusätzliches
<link>nach dem Mandanten-Theme geladen und überschreibt dessen CSS-Variablen (z. B.--vc-accent,--vc-bg). CSS kann kein JavaScript ausführen; die Datei darf cross-origin liegen (kein CORS nötig). Werte für?theme=/?bg=müssen URL-kodiert sein (z. B.%23für#). bg=transparent: die Elternseite scheint durch die Fläche um den Canvas (am sinnvollsten mit?embed=kiosk). Der Video-Canvas selbst bleibt immer deckend – transparent wirkt nur auf den Rahmen/die Letterbox-Ränder.- Platzhalterfarben direkt in der URL (
placeholderBg/placeholderText/placeholderBorder): brandet nur die Platzhalter-Box (das generierte Buchstaben-Motiv, solange kein eigenes Motiv gesetzt ist) – ein Shortcut ohne eigene?theme=-Datei. Akzeptiert jede CSS-Farbe (Hex%23ff5a10,rgb(...),hsl(...), Namen wiewhite) und überschreibt Mandanten-Theme und?theme=; nur gesetzte Parameter überschreiben. Tipp:placeholderBgundplaceholderTextnicht gleich setzen (sonst unsichtbarer Buchstabe). Wer mehr branden will (Akzent, Buttons, Spinner …), nutzt weiterhin?theme=.
Beispiele
Code ansehen URL
https://demo.kreativsimulator.com/ # default
https://demo.kreativsimulator.com/?lang=en # English UI
https://demo.kreativsimulator.com/?product=ec5472c2 # open a product
https://demo.kreativsimulator.com/?product=ec5472c2&lang=fr # language + product
https://demo.kreativsimulator.com/?embed=kiosk # canvas + playback bar only
https://demo.kreativsimulator.com/?header=0&sidebar=0 # header + sidebar off
https://demo.kreativsimulator.com/?timeline=0&playback=0 # timeline + transport off
https://demo.kreativsimulator.com/?effects=0 # effect dropdown off (own picker)
https://demo.kreativsimulator.com/?fullscreen=1 # fullscreen icon also on desktop
https://demo.kreativsimulator.com/?stage=1280x720 # fixed 1280×720 canvas
https://demo.kreativsimulator.com/?bg=%23000000 # black letterbox area
https://demo.kreativsimulator.com/?embed=kiosk&bg=transparent # parent page shows through
https://demo.kreativsimulator.com/?theme=https%3A%2F%2Fcdn.kunde.de%2Fks-theme.css
# Placeholder colors directly (no theme file) — encode # as %23:
https://demo.kreativsimulator.com/?placeholderBg=%23ff5a10&placeholderText=%23ffffff&placeholderBorder=%23ffffff
# … or with rgb()/color names (no %23 needed):
https://demo.kreativsimulator.com/?placeholderBg=rgb(255,90,16)&placeholderText=white&placeholderBorder=white Responsive einbetten
Im Embed-Modus (Chrome aus, z. B. ?embed=kiosk oder ?sidebar=0) füllt der Canvas das iframe vollflächig und bleibt dabei mittig zentriert – kein Links-Offset, kein 1280px-Deckel mehr. Legen Sie das iframe also einfach mit width:100%; height:100% in einen beliebig dimensionierten Eltern-Container (auch Flexbox/Grid). Weicht dessen Seitenverhältnis von 16:9 ab, entsteht eine symmetrische Letterbox (Farbe per ?bg=).
Empfohlenes Rezept – das iframe füllt seinen Flex-/Grid-Container:
Code ansehen HTML
<!-- Any parent container; the iframe fills it completely. -->
<div style="display:flex; width:100%; height:480px;">
<iframe
src="https://demo.kreativsimulator.com/?embed=kiosk"
title="Kreativsimulator"
style="flex:1; border:0;"
allow="fullscreen"
loading="lazy"
></iframe>
</div> Wer ein exakt passendes Seitenverhältnis ohne Letterbox will, gibt dem Wrapper aspect-ratio: 16 / 9:
Code ansehen HTML
<!-- Exact 16:9, no letterbox: constrain the wrapper. -->
<div style="aspect-ratio: 16 / 9; width: 100%;">
<iframe
src="https://demo.kreativsimulator.com/?embed=kiosk"
title="Kreativsimulator"
style="width: 100%; height: 100%; border: 0;"
allow="fullscreen"
loading="lazy"
></iframe>
</div> Mit sichtbarer Sidebar (Standalone-Ansicht ohne ?embed/?sidebar=0) bleibt der Canvas links-bündig (max. 1280px) – die Voll-/Zentrier-Logik greift bewusst nur im Embed-Modus.
Nur der Canvas – alles selbst steuern
Der häufigste Fall: Sie zeigen nur den WebGL-Canvas und bauen die komplette Bedienung selbst. Blenden Sie Header, Sidebar und Buttons aus – per URL mit ?embed=kiosk (Header + Sidebar + Export aus, Abspielleiste bleibt) oder gezielt mit ?header=0&sidebar=0&playback=0&export=0. Zur Laufzeit geht dasselbe per setChrome.
Das Entscheidende: Wiedergabe und Export funktionieren immer per postMessage – unabhängig davon, ob die eingebauten Buttons sichtbar sind. So treiben Ihre eigenen Buttons das iframe; für einen eigenen Fortschrittsbalken lauschen Sie auf das playbackState-Event.
Praktisch ohne Sidebar: Ist die Seitenleiste ausgeblendet, öffnet ein Klick direkt auf eine Plakatfläche im Canvas den Datei-Dialog für genau diesen Platzhalter – so können Endnutzer auch ohne eigene Upload-UI ein Motiv hochladen.
embed=kiosk versteckt das eingebaute Chrome – Ihre Buttons senden play/pause/seek/export. Probieren Sie es unten in der Live-Demo mit den „Chrome“-Schaltern und der eigenen Wiedergabeleiste aus.
Canvas im Kiosk-Modus + eigene Abspielsteuerung, synchron gehalten über das playbackState-Event:
Code ansehen HTML + JS
<!-- Canvas only — your own playback UI drives it from the outside -->
<iframe id="ks" src="https://demo.kreativsimulator.com/?embed=kiosk"
style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>
<button id="play">▶︎</button>
<button id="pause">⏸</button>
<button id="stop">⏹</button>
<button id="back">⏮</button>
<button id="fwd">⏭</button>
<input id="scrub" type="range" min="0" value="0" />
<button id="export">Export</button>
<button id="fs">⛶ Fullscreen</button>
<script>
const iframe = document.getElementById("ks");
const send = (msg) => iframe.contentWindow.postMessage(msg, "*");
const P = "kreativsimulator:";
play.onclick = () => send({ type: P + "play" });
pause.onclick = () => send({ type: P + "pause" });
stop.onclick = () => send({ type: P + "stop" });
back.onclick = () => send({ type: P + "stepBackward" });
fwd.onclick = () => send({ type: P + "stepForward" });
scrub.oninput = (e) => send({ type: P + "seek", frame: Number(e.target.value) });
// Direct export at 1280×720 (no dialog):
export.onclick = () =>
send({ type: P + "export", filename: "creation", width: 1280, height: 720 });
// Fullscreen ON reliably via requestFullscreen on the iframe (the user gesture
// is here, on the click). OFF/toggle could also go via the postMessage event.
fs.onclick = () => {
if (document.fullscreenElement) document.exitFullscreen();
else iframe.requestFullscreen(); // iframe needs allow="fullscreen"
};
window.addEventListener("message", (e) => {
const m = e.data;
if (!m || m.source !== "kreativsimulator") return;
if (m.type === "playbackState") {
scrub.max = m.frameCount - 1;
if (document.activeElement !== scrub) scrub.value = m.frame; // don't fight the drag
play.disabled = m.playing;
pause.disabled = !m.playing;
}
if (m.type === "fullscreenChanged") {
fs.textContent = m.fullscreen ? "⛶ Exit fullscreen" : "⛶ Fullscreen";
}
});
// Ask for the current state once (e.g. after load):
// send({ type: P + "getState" });
</script> Eigenes Design per CSS (theme & bg)
Das iframe übernimmt Ihr Branding über CSS-Variablen. ?theme= lädt eine eigene CSS-Datei nach dem Mandanten-Theme und überschreibt dessen Variablen (z. B. --vc-accent, --vc-bg). ?bg= setzt die Letterbox-Fläche um den Canvas (Farbe oder Bild-URL), ?stage= eine feste Canvas-Pixelgröße.
Einbettung mit Theme + Hintergrund
Code ansehen HTML
<!-- Your own theme + a black letterbox around the canvas -->
<iframe
src="https://demo.kreativsimulator.com/?embed=kiosk&theme=https%3A%2F%2Fcdn.kunde.de%2Fks-theme.css&bg=%23000000"
title="Kreativsimulator"
style="width: 100%; height: 720px; border: 0;"
allow="fullscreen"
loading="lazy"
></iframe> Theme-Vorlage
Vorlage herunterladenks-theme.css Vorlage ansehen kreativsimulator-theme-template.css
/* =============================================================================
Kreativsimulator – Theme-Vorlage (CSS Custom Properties)
=============================================================================
So passt du das Aussehen des eingebetteten Kreativsimulators an deine Marke an.
VERWENDUNG
----------
1. Diese Datei kopieren, Werte unten anpassen, auf einem öffentlich
erreichbaren HTTPS-URL ablegen (z. B. https://cdn.deine-agentur.de/ks-theme.css).
2. Den URL per `?theme=` an die iframe-Einbettung hängen – URL-kodiert:
<iframe src="https://demo.kreativsimulator.com/?theme=https%3A%2F%2Fcdn.deine-agentur.de%2Fks-theme.css"
style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>
HINWEISE
--------
• Die Datei wird als zusätzliches <link> NACH dem Mandanten-Theme geladen und
überschreibt dessen Werte (CSS-Kaskade). Cross-Origin ist erlaubt (kein CORS
nötig) – CSS kann kein JavaScript ausführen.
• Du musst NICHT alle Variablen setzen. Lösche einfach die Zeilen, die du nicht
ändern willst – dann gilt der jeweilige Standard des Simulators/Mandanten.
• Farben: jede gültige CSS-Farbe (#hex, rgb(), hsl(), benannt).
• Den Hintergrund UM den Canvas (Letterbox) steuerst du besser per
`?bg=<farbe|transparent|url>` – nicht über `--vc-bg` (das ist auch der
Canvas-Hintergrund während des Ladens).
========================================================================== */
:root {
/* ── Meta ──────────────────────────────────────────────────────────────
Hell-/Dunkel-Schema. Beeinflusst u. a. native Formular-Elemente.
Werte: dark | light */
--vc-color-scheme: dark;
/* Schriftfamilie der gesamten Oberfläche.
Eigene Webfont? Oben in der Datei per @import laden, z. B.:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap');
und hier referenzieren: 'Inter', system-ui, sans-serif */
--vc-font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
/* ── Flächen ───────────────────────────────────────────────────────────
Grundfarben der UI-Container (Sidebar, Dialoge, Karten). */
--vc-bg: #0a0a0a; /* App-Hintergrund / Canvas-Hintergrund beim Laden */
--vc-surface: #181818; /* Sidebar, Dialog-Flächen */
--vc-surface-raised: #2a2a2a;/* erhöhte Elemente (Tracks, Chips, Inputs) */
--vc-surface-hover: #3a3a3a; /* Hover-Fläche */
--vc-border: #2a2a2a; /* Standard-Rahmenfarbe */
--vc-border-strong: #444444; /* betonte Rahmen */
/* ── Text ──────────────────────────────────────────────────────────────*/
--vc-text: #eeeeee; /* Standard-Textfarbe */
--vc-text-muted: #888888; /* sekundärer Text */
--vc-text-subtle: #666666; /* dezente Hinweise */
--vc-text-on-accent: #ffffff;/* Text auf Akzent-/Primärflächen */
/* ── Akzent (Marke) ────────────────────────────────────────────────────
Wird u. a. für aktive Zustände, Timeline/Abspielkopf und Slider-Punkte
verwendet. `--vc-accent-rgb` MUSS dieselbe Farbe als "R, G, B" enthalten
(ohne rgb()-Klammern) – wird für halbtransparente Hervorhebungen genutzt. */
--vc-accent: #df3b00;
--vc-accent-strong: #ff5722; /* kräftigere Akzentvariante (Hover) */
--vc-accent-rgb: 223, 59, 0; /* = --vc-accent als R, G, B */
--vc-accent-muted: #3a3a3a; /* gedämpfter Akzent-Hintergrund */
/* ── Header (Kopfzeile mit Logo + Produktauswahl) ──────────────────────
Nur relevant, wenn der Header sichtbar ist (sonst per ?header=0 ausblenden). */
--vc-header-bg: transparent; /* Hintergrund der Kopfzeile */
--vc-header-text: #eeeeee; /* Titel-/Header-Text */
--vc-header-text-muted: #888888; /* sekundärer Header-Text */
--vc-header-border: #1a1a1a; /* untere Trennlinie */
--vc-header-border-width: 1px; /* Stärke der Trennlinie (0px = keine) */
--vc-header-padding: 12px 20px; /* Innenabstand der Kopfzeile */
--vc-logo-height: 26px; /* Höhe des Mandanten-Logos */
/* ── Buttons ───────────────────────────────────────────────────────────*/
--vc-button-bg: #2a2a2a; /* Button-Fläche */
--vc-button-bg-hover: #3a3a3a; /* Button-Fläche bei Hover */
--vc-button-text: inherit; /* Button-Textfarbe */
--vc-button-border: #444444; /* Button-Rahmen */
--vc-button-radius: 4px; /* Eckenradius der Buttons */
/* ── Dialoge (Export-Dialog „Export als MP4") ──────────────────────────
Ohne Override folgen sie den Surface-/Border-Variablen. */
--vc-dialog-bg: var(--vc-surface); /* Dialog-Fläche */
--vc-dialog-border: var(--vc-border); /* Dialog-Rahmen */
--vc-dialog-radius: 8px; /* Eckenradius des Dialogs */
--vc-dialog-backdrop: rgba(0, 0, 0, 0.6); /* Abdunklung hinter dem Dialog */
/* ── Eingabefelder & Selects ───────────────────────────────────────────
Gilt für alle Input-/Select-Felder – auch das Effekt-Dropdown bei
Foto-Produkten. Ohne Override folgen sie den Surface-/Text-Variablen. */
--vc-input-bg: var(--vc-surface-raised); /* Feld-Hintergrund */
--vc-input-border: var(--vc-border-strong); /* Feld-Rahmen */
--vc-input-text: var(--vc-text); /* Eingabetext */
--vc-input-radius: 4px; /* Eckenradius der Felder */
--vc-label-text: var(--vc-text-muted); /* Feld-Beschriftungen */
/* ── Slider / Zeitleiste ───────────────────────────────────────────────
Der Abspielkopf und die In/Out-Marken nutzen --vc-accent (s. o.). */
--vc-slider-track: #3a3a3a; /* Track-Farbe der Regler */
/* ── Lade-Spinner (Ladeanzeige beim Initialisieren / Footage-Laden) ────
Ohne Override folgt der Spinner automatisch --vc-accent (Bogen) bzw.
--vc-border (Ring) – diese Zeilen also nur setzen, wenn du ihn abweichend
gestalten willst. */
--vc-spinner-color: var(--vc-accent); /* rotierender Bogen */
--vc-spinner-track: var(--vc-border); /* ruhender Ring */
--vc-spinner-size: 48px; /* Durchmesser */
/* ── Vorschau-Canvas (Rahmen um das Video) ─────────────────────────────*/
--vc-canvas-outline-color: #2a2a2a; /* Outline-Farbe des Canvas */
--vc-canvas-outline-width: 1px; /* Outline-Stärke (0px = kein Rahmen) */
--vc-canvas-radius: 0px; /* Eckenradius des Canvas – z. B. 16px für
runde Ecken (rundet Video, Lade-Fläche
und Rahmen einheitlich). 0px = eckig. */
/* ── Viewport-Rahmen (optionaler Rahmen um die ganze Fläche) ───────────*/
--vc-frame-color: transparent; /* Farbe des Außenrahmens */
--vc-frame-width: 0px; /* Stärke (0px = aus) */
/* ── Platzhalter (Plakatflächen ohne hochgeladenes Motiv) ──────────────
Die generierte „A/B"-Platzhaltertextur. */
--vc-placeholder-bg: #ffffff; /* Hintergrund der Platzhalterfläche */
--vc-placeholder-text: #000000; /* Buchstabe/Beschriftung */
--vc-placeholder-border: #000000; /* Rahmen der Platzhalterfläche */
}
/* =============================================================================
BEISPIEL: helles Marken-Theme (zum Vergleich auskommentiert).
Zum Ausprobieren das obige :root entfernen und dieses aktivieren.
============================================================================*/
/*
:root {
--vc-color-scheme: light;
--vc-bg: #ffffff;
--vc-surface: #ffffff;
--vc-surface-raised: #f2f2f2;
--vc-surface-hover: #e8e8e8;
--vc-border: #e2e2e2;
--vc-border-strong: #c2c2c2;
--vc-text: #1a1a22;
--vc-text-muted: #5e5e68;
--vc-text-subtle: #8c8c94;
--vc-text-on-accent: #ffffff;
--vc-accent: #0066ff;
--vc-accent-strong: #0047b3;
--vc-accent-rgb: 0, 102, 255;
--vc-accent-muted: #d6e4ff;
--vc-header-bg: #ffffff;
--vc-header-text: #1a1a22;
--vc-header-text-muted: #6a6a74;
--vc-header-border: #e2e2e2;
--vc-header-border-width: 1px;
--vc-button-bg: #0066ff;
--vc-button-bg-hover: #0047b3;
--vc-button-text: #ffffff;
--vc-button-border: #0066ff;
--vc-button-radius: 6px;
--vc-slider-track: #e0e0e0;
--vc-canvas-outline-color: #0066ff;
--vc-canvas-outline-width: 2px;
}
*/ - Kein CORS nötig: Die CSS-Datei wird als
<link>geladen (nicht perfetchwie Motive) und darf cross-origin liegen. CSS kann kein JavaScript ausführen. - URL-kodieren: Werte für
?theme=/?bg=müssen URL-kodiert sein (z. B.%23für#,%2Ffür/). - Auch der Lade-Spinner ist themebar:
--vc-spinner-color(rotierender Bogen),--vc-spinner-track(Ring) und--vc-spinner-size(Durchmesser) – ohne Override folgt er automatisch--vc-accentbzw.--vc-border. - Abgerundete Canvas-Ecken:
--vc-canvas-radius(Default0px) rundet den Vorschau-Canvas – Video, Lade-Fläche und Rahmen einheitlich – z. B.--vc-canvas-radius: 16px;in der?theme=-CSS. - Dialoge & Eingabefelder themebar: Der Export-Dialog (
--vc-dialog-bg,--vc-dialog-border,--vc-dialog-radius,--vc-dialog-backdrop) und alle Input-/Select-Felder inkl. des Effekt-Dropdowns bei Foto-Produkten (--vc-input-bg,--vc-input-border,--vc-input-text,--vc-input-radius,--vc-label-text) lassen sich gezielt stylen – ohne Override folgen sie den Surface-/Text-Variablen. - Nur Platzhalterfarben? Dafür brauchen Sie keine Theme-Datei:
?placeholderBg=/?placeholderText=/?placeholderBorder=setzen die Platzhalter-Box direkt per URL (siehe URL-Parameter oben) und überschreiben Theme +?theme=. - Die vollständige Liste der überschreibbaren CSS-Variablen finden Sie in der Theme-Vorlage unten.
Fernsteuerung live ausprobieren
Hier sehen Sie das echte iframe (links) und daneben eine komplett eigene Bedien-UI (rechts) – eigene Produktbilder, eigene Motive, eigene Buttons. Jeder Klick schickt eine postMessage an das iframe. Genau so bauen Sie es auf Ihrer Seite nach; den passenden Code finden Sie direkt darunter.
Echtes iframe von demo.kreativsimulator.com In neuem Tab öffnen
Chrome ein-/ausblenden
Header/Sidebar/Buttons live verstecken → setChrome. „Nur Canvas“ blendet alles aus.
Eigene Wiedergabe
Funktioniert auch ohne sichtbare Buttons. Scrubber via seek, synchron über playbackState.
Ken-Burns-Effekte
Nur bei Foto-Produkten: Kamerafahrten aus ready.effects. Klick → setEffect.
Eigene Produktauswahl
Diese Karten baut Ihre Seite aus dem ready-Event. Klick → setProduct. Foto-Produkte zeigen per getEffects (vorab, ohne Produktwechsel) ihre Effektzahl.
Eigene Motive
Ihre eigenen Platzhalter-Motive. Klick → setCreative (lädt das Bild per CORS).
Eigene Datei je Platzhalter
Bild auf A oder B ziehen → setCreative mit loader. In Produktion laden Sie die Datei auf Ihren CORS-Host und übergeben die URL; hier zur Demo als Data-URL.
Export
Auflösung aus ready.render.presets. Klick → export (MP4).
Lade-Varianten (URL-Parameter)
Lädt das iframe mit Parametern neu – so wirken embed/bg/stage.
Platzhalterfarben (URL)
Brandet nur die Platzhalter-Box direkt per URL – ohne eigene ?theme=-Datei. „Anwenden“ lädt das iframe mit ?placeholderBg/Text/Border neu.
Sprache
Event-Log (iframe → Ihre Seite)
- Noch keine Events empfangen …
Der folgende Code steuert exakt diese Live-Demo. Übernehmen Sie ihn als Ausgangspunkt:
Code ansehen HTML + JS
<iframe id="ks" src="https://demo.kreativsimulator.com/"
style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>
<script>
const iframe = document.getElementById("ks");
const send = (msg) => iframe.contentWindow.postMessage(msg, "*");
window.addEventListener("message", (e) => {
const m = e.data;
if (!m || m.source !== "kreativsimulator") return;
if (m.type === "ready") {
// Build your own buttons from the product list
for (const p of m.products) {
const btn = document.createElement("button");
btn.textContent = p.name;
btn.onclick = () =>
send({ type: "kreativsimulator:setProduct", code: p.code });
document.body.appendChild(btn);
}
// Build your own resolution picker + export button from m.render.presets
const sel = document.createElement("select");
for (const r of m.render.presets) {
const o = document.createElement("option");
o.value = r.width + "x" + r.height;
o.textContent = r.label;
sel.appendChild(o);
}
const exportBtn = document.createElement("button");
exportBtn.textContent = "Export";
exportBtn.onclick = () => {
const [width, height] = sel.value.split("x").map(Number);
send({ type: "kreativsimulator:export", filename: "creation", width, height });
};
document.body.append(sel, exportBtn);
}
// The product is active now → only here may you target a placeholder.
if (m.type === "productChanged") {
const first = m.loaders[0]; // take the name from the event
if (first) {
send({
type: "kreativsimulator:setCreative",
url: "https://cdn.your-agency.com/creative.png",
loader: first.name, // this placeholder only
});
}
}
if (m.type === "error") console.warn("KS error:", m.message);
});
// Creative on ALL placeholders (no loader) — fine right after `ready`:
// send({ type: "kreativsimulator:setCreative", url: "https://cdn.your-agency.com/creative.png" });
</script> postMessage-API
Bauen Sie eine eigene UI und steuern Sie das iframe per window.postMessage. Das iframe sendet außerdem Events zurück (u. a. die Liste der verfügbaren Produkt-Codes).
Eingehende Befehle (Ihre Seite → iframe)
| Nachricht | Wirkung |
|---|---|
{ type: "kreativsimulator:setProduct", code: "ec5472c2" } | Lädt das Produkt mit diesem Code. |
{ type: "kreativsimulator:setCreative", url: "https://…/motiv.png" } | Legt das Bild/Video als Motiv auf alle Platzhalter. |
{ type: "kreativsimulator:setCreative", url: "…", loader: "Loader A" } | Belegt nur den genannten Platzhalter. |
{ type: "kreativsimulator:clearCreative", loader?: "Loader A" } | Setzt einen (oder ohne loader alle) Platzhalter auf den Default zurück. |
{ type: "kreativsimulator:setLanguage", lang: "fr" } | Schaltet die UI-Sprache (de/en/fr/it). |
{ type: "kreativsimulator:setEffect", id: "static-5s" } | Foto-Produkte: wählt einen Eintrag aus ready.effects – ein Statisch-Preset (static-5s/static-10s, immer vorhanden) oder einen benannten Ken-Burns-Effekt. id: null = reines Standbild (1 Frame). Ändert die Timeline-Länge → es folgt ein playbackState. |
{ type: "kreativsimulator:getEffects", code: "ec5472c2" } | Fragt die Effektliste eines beliebigen Produkts ab, ohne es zu aktivieren (Live-Ansicht bleibt unverändert) → Antwort als effects-Event. Für einen eigenen Effekt-Picker je Produkt – noch vor setProduct. |
{ type: "kreativsimulator:play" } · pause · stop | Startet / pausiert / stoppt (zurück an den Anfang) die Wiedergabe. |
{ type: "kreativsimulator:stepForward", frames?: 1 } · stepBackward | Springt frames Bilder vor/zurück (Default 1) und pausiert. |
{ type: "kreativsimulator:seek", frame: 120 } | Springt zu einem absoluten Bild-Index (0…frameCount-1). |
{ type: "kreativsimulator:export", filename?, width?, height? } | Startet den MP4-Export. Mit width+height direkt in beliebiger Auflösung; ohne öffnet sich der Export-Dialog. |
{ type: "kreativsimulator:setChrome", header?, sidebar?, playback?, timeline?, export?, effects? } | Blendet einzelne UI-Bereiche zur Laufzeit ein/aus (jeweils true/false). effects = Effekt-Dropdown (Foto-Produkte). |
{ type: "kreativsimulator:fullscreen", enabled? } | Vollbild: true=ein, false=aus, ohne enabled=umschalten (siehe Hinweis). |
{ type: "kreativsimulator:getState" } | Fordert den aktuellen Wiedergabe-Zustand an → Antwort als playbackState. |
Ausgehende Events (iframe → Ihre Seite)
Code ansehen JS
{ source: "kreativsimulator", v: 1, type: "ready",
product: "ec5472c2", locale: "de",
products: [{ code: "ec5472c2", name: "City-Light …" }, …],
loaders: [{ name: "Loader A", aspectRatio: 2.96 }, …],
// native render resolution (16:9) + suggested export presets
render: { width: 1280, height: 720, aspectRatio: 1.7778,
presets: [{ label: "E-Mail / WhatsApp (640×360)", width: 640, height: 360 },
{ label: "Standard HD (1280×720)", width: 1280, height: 720 },
{ label: "YouTube / Full HD (1920×1080)", width: 1920, height: 1080 }] },
// photo products (productType "bild"): effects[] = two always-present static
// presets (static-5s, static-10s) + named Ken-Burns effects; default = static-5s.
// video products report isPhoto:false, effects:[], selectedEffect:null.
isPhoto: true,
effects: [{ id: "static-5s", name: "Static (5s)", durationFrames: 125 },
{ id: "static-10s", name: "Static (10s)", durationFrames: 250 },
{ id: "fx-a", name: "Effect A", durationFrames: 125 }, …],
selectedEffect: "static-5s" }
{ source: "kreativsimulator", v: 1, type: "productChanged", code: "ec5472c2",
loaders: [{ name: "Loader A", aspectRatio: 2.96 }, …],
isPhoto: true,
effects: [{ id: "static-5s", name: "Static (5s)", durationFrames: 125 },
{ id: "static-10s", name: "Static (10s)", durationFrames: 250 },
{ id: "fx-a", name: "Effect A", durationFrames: 125 }, …],
selectedEffect: "static-5s" }
// reply to getEffects {code}: a product's effect list WITHOUT activating it.
// same fields as productChanged (incl. the static presets), plus code.
// video products report isPhoto:false, effects:[], selectedEffect:null.
{ source: "kreativsimulator", v: 1, type: "effects", code: "ec5472c2",
isPhoto: true,
effects: [{ id: "static-5s", name: "Static (5s)", durationFrames: 125 },
{ id: "static-10s", name: "Static (10s)", durationFrames: 250 },
{ id: "fx-a", name: "Effect A", durationFrames: 125 }, …],
selectedEffect: "static-5s" }
// playback state: on play/pause, ~4×/s while playing, after seek/stop/step, and on getState
// for photo products, frameCount equals the active effect's duration
{ source: "kreativsimulator", v: 1, type: "playbackState",
frame: 120, playing: true, frameCount: 250, fps: 25 }
// confirmation after setChrome, with the new visibility state
{ source: "kreativsimulator", v: 1, type: "chromeChanged",
header: false, sidebar: false, playback: true, timeline: true, export: false, effects: false }
// fullscreen state — on every change (e.g. ESC); for syncing your own button
{ source: "kreativsimulator", v: 1, type: "fullscreenChanged", fullscreen: true }
{ source: "kreativsimulator", v: 1, type: "error", message: "…", code, loader } Filtern Sie eingehende Nachrichten immer auf source === "kreativsimulator". v ist die Protokoll-Version (aktuell 1).
Vollständiges Beispiel
Eigene Buttons aus der Produktliste, ein platzhalter-gezieltes Motiv (korrekte Reihenfolge) und ein eigener Auflösungs-Picker aus render.presets:
Code ansehen HTML + JS
<iframe id="ks" src="https://demo.kreativsimulator.com/"
style="width:100%;height:720px;border:0" allow="fullscreen"></iframe>
<script>
const iframe = document.getElementById("ks");
const send = (msg) => iframe.contentWindow.postMessage(msg, "*");
window.addEventListener("message", (e) => {
const m = e.data;
if (!m || m.source !== "kreativsimulator") return;
if (m.type === "ready") {
// Build your own buttons from the product list
for (const p of m.products) {
const btn = document.createElement("button");
btn.textContent = p.name;
btn.onclick = () =>
send({ type: "kreativsimulator:setProduct", code: p.code });
document.body.appendChild(btn);
}
// Build your own resolution picker + export button from m.render.presets
const sel = document.createElement("select");
for (const r of m.render.presets) {
const o = document.createElement("option");
o.value = r.width + "x" + r.height;
o.textContent = r.label;
sel.appendChild(o);
}
const exportBtn = document.createElement("button");
exportBtn.textContent = "Export";
exportBtn.onclick = () => {
const [width, height] = sel.value.split("x").map(Number);
send({ type: "kreativsimulator:export", filename: "creation", width, height });
};
document.body.append(sel, exportBtn);
}
// The product is active now → only here may you target a placeholder.
if (m.type === "productChanged") {
const first = m.loaders[0]; // take the name from the event
if (first) {
send({
type: "kreativsimulator:setCreative",
url: "https://cdn.your-agency.com/creative.png",
loader: first.name, // this placeholder only
});
}
}
if (m.type === "error") console.warn("KS error:", m.message);
});
// Creative on ALL placeholders (no loader) — fine right after `ready`:
// send({ type: "kreativsimulator:setCreative", url: "https://cdn.your-agency.com/creative.png" });
</script> Wichtig
- Reihenfolge bei Produktwechsel: Nach
setProductist das neue Produkt erst aktiv, sobald dasproductChanged-Event eintrifft. Platzhalter-gezielte Befehle (setCreative/clearCreativemitloader) erst danach senden – vorher kennt das iframe nur die Platzhalter des alten Produkts. Ein Produktwechsel setzt zudem alle Motive zurück. - Eigene Bedienelemente: Wiedergabe (
play/pause/stop/step…/seek) undexportfunktionieren immer – egal ob die eingebauten Buttons sichtbar sind. Blenden Sie sie mit?embed=kioskaus und steuern Sie alles selbst. - Export-Auflösung frei wählen:
exportmitwidth+heightrendert in beliebiger Auflösung. Native Auflösung (1280×720, 16:9) und Presets liefertready.render– Seitenverhältnis 16:9 halten, sonst verzerrt das Bild. - Foto-Produkte & Ken-Burns-Effekte: Manche Produkte sind Standbilder mit benannten Kamerafahrten.
ready/productChangedmelden dannisPhoto: trueund eine Listeeffects({ id, name, durationFrames }). Diese beginnt immer mit zwei Statisch-Presets (static-5s= 5 s,static-10s= 10 s), gefolgt von den benannten Effekten; beim Laden ist automatischstatic-5saktiv (selectedEffect). MitsetEffect { id }wählen Sie einen anderen Eintrag (oderid: nullfür ein reines Standbild, 1 Frame). Wiedergabe und Export funktionieren wie bei Video;playbackState.frameCountentspricht der Dauer des aktiven Eintrags. - Effekte vorab abfragen (ohne Produktwechsel):
ready/productChangedliefern Effekte nur für das aktive Produkt. Für einen Effekt-Picker zu anderen Produkten – ohne die Live-Ansicht umzuschalten – senden SiegetEffects { code }und lauschen auf daseffects-Event (gleiche Felder wieproductChanged, pluscode). So holen Sieid/namejedes Effekts, die Sie später mitsetEffect(nachsetProductauf diesen Code) ansteuern. - Vollbild zuverlässig einschalten: Browser erlauben das Einschalten nur als direkte Reaktion auf eine User-Geste – eine
fullscreen-postMessage hat diese meist nicht und kann blockiert werden. Rufe daher auf deiner Seite beim Klickiframe.requestFullscreen()auf (iframe brauchtallow="fullscreen"); die postMessage eignet sich für Aus/Toggle. Den Zustand liefertfullscreenChanged. - Platzhalter-Namen sind nicht frei wählbar – verwenden Sie exakt einen
nameaus demloaders[]-Array vonreadybzw.productChanged. - CORS: Bei
setCreativelädt das iframe die Bild-/Video-URL perfetch. Der Host Ihrer Datei muss daherAccess-Control-Allow-Originsenden, sonst kommt einerror-Event zurück. - Sicherheit: Welche Seiten das iframe einbetten dürfen, ist serverseitig per
frame-ancestorsfestgelegt – nur diese können überhaupt Nachrichten senden.
Gut zu wissen
- Kein API-Key nötig – die Authentifizierung läuft vollständig serverseitig.
- Der Nutzer kann den Simulator direkt im iframe bedienen oder Sie steuern ihn per postMessage von Ihrer Seite.
- Der iframe lädt Video-Footage – eine stabile Verbindung wird empfohlen.
Troubleshooting
Der iframe bleibt leer / weiße Fläche
Mit hoher Wahrscheinlichkeit ist die einbettende Domain nicht freigeschaltet. Die Browser-Konsole (F12) zeigt dann „Refused to frame … frame-ancestors …“. Schicken Sie uns die exakte Domain (inkl. https:// und ggf. Subdomain), wir schalten sie frei.
Der iframe zeigt „403“
Der Mandant ist serverseitig noch nicht vollständig konfiguriert (kein API-Key hinterlegt). Bitte bei uns melden.
Ein Motiv erscheint nicht (error-Event)
Die Motiv-URL sendet kein CORS, oder der loader-Name passt nicht zum aktiven Produkt. Prüfen Sie Access-Control-Allow-Origin der Bild-URL und senden Sie loader-gezielte Befehle erst nach dem productChanged-Event.
Bereit zum Einbetten?
Schicken Sie uns Ihre Domain(s) – wir schalten die Einbettung frei und Sie sind in Minuten live.