YouTube-Banner, vorlaeufig
2560 x 1440, Botschaft in der Mitte fuer alle Geraete, G-Waben drumherum. Rendern mit kanaele/rendern.sh, die Bereiche je Geraet mit "zonen". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b61f029a36
commit
f38cbfe12c
4 files changed
+118
No files matched your search
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Rendert das YouTube-Banner als PNG in 2560 x 1440, mit Chrome ohne Fenster.
|
||||||
|
# ./rendern.sh youtube-banner.png
|
||||||
|
# ./rendern.sh zonen youtube-banner-zonen.png, mit den Bereichen je Gerät
|
||||||
|
cd "$(dirname "$0")" || exit 1
|
||||||
|
CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||||||
|
NAME=youtube-banner
|
||||||
|
SUCHE=""
|
||||||
|
if [ "$1" = "zonen" ]; then NAME=youtube-banner-zonen; SUCHE="?zonen"; fi
|
||||||
|
"$CHROME" --headless=new --disable-gpu --hide-scrollbars --allow-file-access-from-files \
|
||||||
|
--force-device-scale-factor=1 --window-size=2560,1440 --virtual-time-budget=4000 \
|
||||||
|
--screenshot="$PWD/$NAME.png" "file://$PWD/youtube-banner.html$SUCHE" 2>/dev/null
|
||||||
|
ls -la "$NAME.png"
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 383 KiB |
@@ -0,0 +1,105 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>YouTube-Banner HiveGrid</title>
|
||||||
|
<link rel="stylesheet" href="../assets/fonts/manrope.css">
|
||||||
|
<style>
|
||||||
|
/* YouTube-Banner, 2560 x 1440 (Empfehlung von Google, Stand 10/2026).
|
||||||
|
Was jedes Gerät sieht:
|
||||||
|
Fernseher das ganze Bild
|
||||||
|
Desktop der Streifen in der Mitte, 2560 x 423
|
||||||
|
Handy nur 1546 x 423 in der Mitte. Darin steht alles Wichtige.
|
||||||
|
Keine Schatten und Rahmen, das verbietet Google ausdrücklich.
|
||||||
|
Gerendert mit ./rendern.sh. Mit ?zonen sieht man die Bereiche. */
|
||||||
|
:root {
|
||||||
|
--navy: #0F1A2E;
|
||||||
|
--gelb: #F1B729;
|
||||||
|
--weiss: #FFFFFF;
|
||||||
|
--grau: #B9BDC9;
|
||||||
|
}
|
||||||
|
html, body { margin: 0; background: var(--navy); }
|
||||||
|
.banner {
|
||||||
|
position: relative; width: 2560px; height: 1440px; overflow: hidden;
|
||||||
|
background: var(--navy); font-family: Manrope, sans-serif;
|
||||||
|
}
|
||||||
|
#waben { position: absolute; inset: 0; }
|
||||||
|
.mitte {
|
||||||
|
position: absolute; left: 507px; top: 508px; width: 1546px; height: 423px;
|
||||||
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.wortmarke { height: 76px; display: block; margin-bottom: 34px; }
|
||||||
|
h1 {
|
||||||
|
margin: 0; color: var(--weiss); font-weight: 800; font-size: 80px;
|
||||||
|
line-height: 1.08; letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
/* Akzent wie im Theme modern: das Wort in Gelb mit einem Balken darunter. */
|
||||||
|
h1 .a { color: var(--gelb); position: relative; white-space: nowrap; }
|
||||||
|
h1 .a::after {
|
||||||
|
content: ""; position: absolute; left: 0; right: 0.12em; bottom: -0.04em;
|
||||||
|
height: 0.09em; background: var(--gelb);
|
||||||
|
}
|
||||||
|
.unter {
|
||||||
|
margin: 34px 0 0; color: var(--grau); font-weight: 600; font-size: 38px;
|
||||||
|
letter-spacing: -0.005em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hilfslinien, nur mit ?zonen */
|
||||||
|
.zone { position: absolute; border: 3px dashed; pointer-events: none; display: none; }
|
||||||
|
.zonen .zone { display: block; }
|
||||||
|
.zone span { position: absolute; left: 12px; top: 8px; font: 700 26px Manrope, sans-serif; }
|
||||||
|
.z-handy { left: 507px; top: 508px; width: 1546px; height: 423px; border-color: #FF4D4D; color: #FF4D4D; }
|
||||||
|
.z-tablet { left: 352px; top: 508px; width: 1855px; height: 423px; border-color: #4DD2FF; color: #4DD2FF; }
|
||||||
|
.z-desktop { left: 0; top: 508px; width: 2560px; height: 423px; border-color: #7CFF4D; color: #7CFF4D; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="banner" id="banner">
|
||||||
|
<svg id="waben" width="2560" height="1440" viewBox="0 0 2560 1440" aria-hidden="true"></svg>
|
||||||
|
<div class="mitte">
|
||||||
|
<img class="wortmarke" src="../assets/brand/logo-white.svg" alt="HiveGrid">
|
||||||
|
<h1>Dein Branchenprogramm bleibt.<br>HiveGrid kommt <span class="a">drumherum.</span></h1>
|
||||||
|
<p class="unter">Software für Handwerksbetriebe, entstanden in einem SHK-Betrieb</p>
|
||||||
|
</div>
|
||||||
|
<div class="zone z-desktop"><span>Desktop 2560 × 423</span></div>
|
||||||
|
<div class="zone z-tablet"><span>Tablet 1855 × 423</span></div>
|
||||||
|
<div class="zone z-handy"><span>Handy, alle Geräte 1546 × 423</span></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
// Das Wabenfeld der Website (cta-honeycomb.svg): gelbe G-Waben auf Dunkel.
|
||||||
|
// Außen volle G-Waben, zur Mitte hin nur noch der Umriss der Wabe, immer
|
||||||
|
// dünner, dann nichts mehr, damit die Schrift frei steht. Kein halbdurch-
|
||||||
|
// sichtiges Gelb: Das wird auf Navy trüb.
|
||||||
|
// Fester Zufall, damit jedes Rendern gleich aussieht.
|
||||||
|
const G = "384.5,166.5 336.4,83.2 192.2,166.5 288.3,166.5 240.3,249.7 144.2,249.7 96.1,166.5 144.2,83.2 336.4,83.2 298,16.8 288.3,0 96.1,0 0,166.5 96.1,332.9 288.3,332.9";
|
||||||
|
const WABE = "384.5,166.5 288.3,332.9 96.1,332.9 0,166.5 96.1,0 288.3,0";
|
||||||
|
const B = 168, S = B / 384.5, H = 332.9 * S, LUECKE = 22;
|
||||||
|
const DX = 0.75 * B + LUECKE, DY = H + LUECKE * 1.1;
|
||||||
|
let saat = 7;
|
||||||
|
const zufall = () => ((saat = (saat * 16807) % 2147483647) / 2147483647);
|
||||||
|
const svg = document.getElementById("waben");
|
||||||
|
let inhalt = "";
|
||||||
|
for (let spalte = -1; spalte * DX < 2560 + B; spalte++) {
|
||||||
|
for (let zeile = -1; zeile * DY < 1440 + H; zeile++) {
|
||||||
|
const x = spalte * DX, y = zeile * DY + (spalte % 2 ? DY / 2 : 0);
|
||||||
|
const mx = x + B / 2, my = y + H / 2;
|
||||||
|
// 0 in der Mitte, 1 am Rand. Waagerecht ab 640 px vom Zentrum, senkrecht ab 300.
|
||||||
|
const quer = Math.max(Math.abs(mx - 1280) - 640, 0) / 600;
|
||||||
|
const hoch = Math.max(Math.abs(my - 720) - 300, 0) / 420;
|
||||||
|
const staerke = Math.min(1, Math.max(quer, hoch * 0.85)) + 0.06 * (zufall() - 0.5);
|
||||||
|
const lage = `transform="translate(${x.toFixed(1)} ${y.toFixed(1)}) scale(${S.toFixed(5)})"`;
|
||||||
|
if (staerke >= 0.5) {
|
||||||
|
inhalt += `<polygon points="${G}" fill="#F1B729" ${lage}/>`;
|
||||||
|
} else if (staerke >= 0.12) {
|
||||||
|
// Strichstärke in Pixeln, über die Skalierung zurückgerechnet.
|
||||||
|
const strich = (1.5 + 5 * (staerke - 0.12) / 0.38) / S;
|
||||||
|
inhalt += `<polygon points="${WABE}" fill="none" stroke="#F1B729" stroke-width="${strich.toFixed(1)}" stroke-linejoin="miter" ${lage}/>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
svg.innerHTML = inhalt;
|
||||||
|
if (location.search.includes("zonen")) document.getElementById("banner").classList.add("zonen");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 356 KiB |
Reference in new issue
Block a user