/* * Zeichnet die Bildkarten des Solarchecks von EB Solar und rastert sie zu PNG. * * Die Formularbausteine zeigen eine Auswahl als Bildkarten, sobald eine Option ein Bild aus der * Mediathek hat - und die Mediathek nimmt JPEG, PNG und WebP, kein SVG. Deshalb entstehen die * Symbole hier als SVG (leicht zu ändern, alles in einer Datei) und werden mit Chromium auf * 800 × 600 gerastert, dem Seitenverhältnis 4:3 der Karte. Stil wie die übrigen Symbole der * Website: dünne Linie in Tinte, runde Enden, ein roter Akzent, helle Fläche dahinter. * * node scripts/build-ebsolar-options.mjs → var/ebsolar-assets/options/*.png und *.svg */ import { chromium } from 'playwright'; import { mkdir, writeFile } from 'node:fs/promises'; const ziel = process.argv[2] || 'var/ebsolar-assets/options'; const TINTE = '#252b30', ROT = '#b52c2c', HELL = '#f5f6f6', PAPIER = '#ffffff', GRAU = '#c9ced0'; /** Ein Bild: 800 × 600, helle Fläche, Inhalt in der Mitte. */ const bild = (inhalt) => ` ${inhalt} `; /** Eine Person: Kopf und Schultern. */ const person = (x, y, s = 1, farbe = TINTE) => ` `; /** Ein Haus: Wände plus Dach nach Angabe; das Dach ist der Akzent. */ const haus = (dach) => ` ${dach}`; /** Ein Dach als schräge Fläche mit Modulen im Raster. */ const module = (spalten, zeilen) => { const x0 = 160, y0 = 150, b = 480, h = 300, scher = 90; const zellen = []; for (let z = 0; z < zeilen; z++) { for (let s = 0; s < spalten; s++) { const bx = b / spalten, bh = h / zeilen; const x = x0 + s * bx + (z * bh) * (scher / h), y = y0 + z * bh; zellen.push(``); } } return `${zellen.join('')}`; }; const fragezeichen = (x, y, s = 1) => ``; const batterie = (inhalt, farbe = TINTE) => ` ${inhalt}`; const bilder = { // Wie viele Personen leben im Haushalt? 'personen-1': person(400, 320, 1.3), 'personen-2': person(300, 320, 1.15) + person(500, 320, 1.15), 'personen-3-4': person(210, 330) + person(400, 330) + person(590, 330), 'personen-4-plus': person(160, 330, .85) + person(320, 330, .85) + person(480, 330, .85) + person(640, 330, .85) + ``, // Welche Form hat Ihr Dach? 'dach-flach': haus(``), 'dach-sattel': haus(``), 'dach-pult': haus(``), 'dach-versetzt': ` `, 'dach-sonstiges': haus(``) + fragezeichen(400, 250, 1.1), // Wie groß ist Ihre Dachfläche? 'flaeche-50': module(2, 1), 'flaeche-100': module(3, 2), 'flaeche-200': module(5, 3), 'flaeche-200-plus': module(7, 4), 'flaeche-unsicher': `` + fragezeichen(400, 300, 1.4), // Aus welchem Material besteht die Dacheindeckung? 'eindeckung-ziegel': [0, 1, 2, 3].map(z => [0, 1, 2, 3, 4].map(s => { if (z % 2 === 1 && s === 4) return ''; const x = 150 + s * 100 + (z % 2) * 50, y = 170 + z * 80; return ``; }).join('')).join(''), 'eindeckung-bitumen': ` `, 'eindeckung-blech': ` `, 'eindeckung-anderes': `` + fragezeichen(400, 300, 1.4), // Wünschen Sie einen Stromspeicher? 'speicher-ja': batterie(``), 'speicher-nein': batterie('', GRAU) + ``, }; await mkdir(ziel, { recursive: true }); const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 800, height: 600 }, deviceScaleFactor: 1 }); for (const [name, inhalt] of Object.entries(bilder)) { const svg = bild(inhalt); await writeFile(`${ziel}/${name}.svg`, svg); await page.setContent(`${svg}`); await page.locator('svg').screenshot({ path: `${ziel}/${name}.png`, omitBackground: false }); console.log('gezeichnet:', name); } await browser.close();