feat(store): App-Store-Variante der Marketing-Screenshots (1320x2868, DE/EN)

Gleiche Vorlage mit Apple-Modus: höhere Fläche, größeres Handy und eine
iOS-Statusleiste mit Dynamic Island über der Android-Statusleiste
(Richtlinie 2.3.10). render.sh erzeugt jetzt Play- und Apple-Satz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-09 17:47:05 +02:00
1 parent d9c061bfb8
commit ce0352ec61
18 files changed
+54 -16

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

+19 -13
View File
@@ -1,19 +1,25 @@
#!/bin/sh
# Rendert die Play-Store-Marketing-Screenshots (1080x1920) per Headless-Chrome.
# Rendert die Store-Marketing-Screenshots per Headless-Chrome:
# out/<de|en>/ Google Play, 1080x1920
# out-apple/<de|en>/ App Store iPhone 6.9", 1320x2868 (mit iOS-Statusleiste)
# Aufruf: sh render.sh
cd "$(dirname "$0")"
CHROME="/c/Program Files/Google/Chrome/Application/chrome.exe"
# Reihenfolge = Reihenfolge im Play Store (Dateien werden 01-…, 02-… nummeriert)
# Reihenfolge = Reihenfolge im Store (Dateien werden 01-…, 02-… nummeriert)
SLIDES="hero profil tierarten nachrichten gesundheit benachrichtigungen raenge spinnen"
for lang in de en; do
mkdir -p "out/$lang"
i=0
for s in $SLIDES; do
i=$((i + 1))
"$CHROME" --headless=new --disable-gpu --hide-scrollbars --force-device-scale-factor=1 \
--window-size=1080,1920 --virtual-time-budget=5000 \
--screenshot="$(cygpath -w "$PWD/out/$lang/$(printf %02d $i)-$s.png")" \
"file:///$(cygpath -m "$PWD/template.html")?s=$s&lang=$lang" 2>/dev/null
render() { # $1 = Plattform, $2 = Ausgabeordner, $3 = Fenstergröße
for lang in de en; do
mkdir -p "$2/$lang"
i=0
for s in $SLIDES; do
i=$((i + 1))
"$CHROME" --headless=new --disable-gpu --hide-scrollbars --force-device-scale-factor=1 \
--window-size="$3" --virtual-time-budget=5000 \
--screenshot="$(cygpath -w "$PWD/$2/$lang/$(printf %02d $i)-$s.png")" \
"file:///$(cygpath -m "$PWD/template.html")?s=$s&lang=$lang&p=$1" 2>/dev/null
done
done
done
ls out/*
}
render play out 1080,1920
render apple out-apple 1320,2868
ls out/* out-apple/*
@@ -26,6 +26,23 @@
.hero h1 { position: absolute; top: 140px; left: 80px; font-size: 128px; }
.hero .arch { left: -120px; right: 180px; top: 980px; border-radius: 520px 520px 0 0; }
.hero .phone { left: 260px; top: 560px; width: 760px; transform: rotate(-10deg); transform-origin: top left; }
/* Apple (1320x2868): gleiche Gestaltung, nur höhere Fläche und größeres Handy */
html.apple { zoom: calc(1320 / 1080); }
html.apple, html.apple body { height: 2347px; }
.apple .arch { top: 900px; }
.apple .std h1 { top: 170px; }
.apple .std .phone { top: 500px; width: 780px; }
.apple .hero .arch { top: 1080px; }
.apple .hero .phone { top: 600px; width: 800px; }
/* iOS-Statusleiste über der Android-Statusleiste (Apple-Richtlinie 2.3.10) */
.phone { container-type: inline-size; }
.sb { position: absolute; left: 14px; right: 14px; top: 14px; height: 11cqw; border-radius: 58px 58px 0 0;
display: flex; align-items: center; justify-content: space-between; padding: 0 7cqw 0 10cqw;
font: 600 4cqw/1 -apple-system, "SF Pro Text", "Inter", sans-serif; }
.sb .island { position: absolute; left: 50%; top: 2.4cqw; width: 26cqw; height: 7.4cqw; border-radius: 4cqw;
background: #000; transform: translateX(-50%); }
.sb svg { height: 3.4cqw; margin-left: 1.4cqw; }
.tile { position: absolute; width: 132px; height: 132px; border-radius: 34px; display: grid; place-items: center;
font-size: 72px; box-shadow: 0 18px 36px rgba(60, 35, 10, .18); }
.tile img { width: 100%; height: 100%; border-radius: 34px; }
@@ -52,7 +69,7 @@
en: "Every pet gets its own profile",
},
tierarten: {
layout: "std", img: "src/tierarten.png", arch: "#E3D7FB",
layout: "std", img: "src/tierarten.png", sb: "#FAFAFA", arch: "#E3D7FB",
de: "16 Tierarten. Ein Zuhause.",
en: "16 species. One home.",
},
@@ -77,7 +94,7 @@
en: "Invite friends, climb the ranks",
},
spinnen: {
layout: "std", img: "src/spinnen.png", arch: "#CDEBC4",
layout: "std", img: "src/spinnen.png", sb: "#111111", arch: "#CDEBC4",
de: "Angst vor Spinnen? Einfach ausblenden",
en: "Scared of spiders? Just hide them",
},
@@ -87,11 +104,26 @@
const s = SLIDES[q.get("s") || "hero"];
const lang = q.get("lang") || "de";
document.documentElement.lang = lang;
const apple = q.get("p") === "apple";
if (apple) document.documentElement.classList.add("apple");
document.body.className = s.layout;
const sbBg = s.sb || "#FFFFFF";
const sbInk = sbBg === "#111111" ? "#FFFFFF" : "#000000";
const statusBar = !apple ? "" :
`<div class="sb" style="background:${sbBg};color:${sbInk}">
<span>9:41</span><div class="island"></div>
<span>
<svg viewBox="0 0 18 12" fill="${sbInk}"><rect x="0" y="8" width="3" height="4" rx="1"/><rect x="5" y="5.5" width="3" height="6.5" rx="1"/><rect x="10" y="3" width="3" height="9" rx="1"/><rect x="15" y="0" width="3" height="12" rx="1"/></svg>
<svg viewBox="0 0 16 12" fill="${sbInk}"><path d="M8 12 5.6 9.2a3.4 3.4 0 0 1 4.8 0z"/><path d="M8 5.4a7 7 0 0 1 4.9 2l-1.4 1.6a5 5 0 0 0-7 0L3.1 7.4A7 7 0 0 1 8 5.4z"/><path d="M8 0a12 12 0 0 1 8 3.2l-1.4 1.6a10 10 0 0 0-13.2 0L0 3.2A12 12 0 0 1 8 0z"/></svg>
<svg viewBox="0 0 27 12"><rect x=".5" y=".5" width="23" height="11" rx="3" fill="none" stroke="${sbInk}" opacity=".4"/><rect x="2" y="2" width="20" height="8" rx="1.8" fill="${sbInk}"/><rect x="25" y="4" width="1.6" height="4" rx=".8" fill="${sbInk}" opacity=".4"/></svg>
</span>
</div>`;
document.body.innerHTML =
`<div class="arch" style="background:${s.arch}"></div>
<h1>${s[lang]}</h1>
<div class="phone"><img src="${s.img}"></div>` +
<div class="phone"><img src="${s.img}">${statusBar}</div>` +
(s.tiles || []).map(t =>
`<div class="tile" style="left:${t.x}px;top:${t.y}px;transform:rotate(${t.r}deg);background:${t.bg || "none"}">${t.html}</div>`
).join("");