Laptop-Stand uebernommen, Projektstand von hier behalten
Beide Seiten hatten state/post1.json geaendert. Der Code, das neue Titel-Mockup und die umbenannten Tags kommen vom Laptop; der Projektstand ist der von hier (Rahmen "rund", Positionen von 23:30). Bewusst so entschieden -- die Positionsarbeit vom Laptop faellt damit weg. Der Stand steht noch auf v2. Beim naechsten Laden rechnet ihn das Skript auf v3 hoch und entfernt dabei den szene-Eintrag, weil das Titel-Mockup ein anderes Bild mit anderem Format geworden ist. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
3c0b22aa9a
4 files changed
+63
-125
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1011 KiB |
+57
-114
@@ -651,70 +651,13 @@
|
|||||||
width: 430px; height: auto;
|
width: 430px; height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── Szenen-Mockup ──────────────────────────────────────────────────────
|
/* ─── Laptop mit Board ───────────────────────────────────────────────────
|
||||||
Macbook Air + iPad Pro in Perspektive (Pixeden-PSD, Hintergrund entfernt,
|
Fertiges Mockup: der Screen ist Teil des Bildes. Kein ausgeknocktes
|
||||||
beide Displays ausgeknockt). Anders als beim frontalen Laptop reicht kein
|
Display, keine Projektion per matrix3d, kein zweiter Screenshot dahinter.
|
||||||
Rechteck: die Displayflächen sind Vierecke. Die Screens werden deshalb
|
Damit fallen auch die gemessenen Vierecke und Eckradien weg, die das
|
||||||
per matrix3d hineinprojiziert. Die Matrizen wurden aus den Eckpunkten der
|
vorherige Szenen-Mockup gebraucht hat. */
|
||||||
Smart-Objekte im PSD gerechnet und bilden Design-Pixel auf Bildpixel des
|
.szene { position: relative; width: 720px; }
|
||||||
5742 px breiten Originals ab; --sk skaliert von dort auf die Breite in
|
.szene-dev { width: 100%; height: auto; display: block; }
|
||||||
der Slide und wird beim Anwenden der Größe gesetzt. */
|
|
||||||
.szene { position: relative; width: 980px; }
|
|
||||||
.szene-dev { width: 100%; display: block; position: relative; z-index: 2; }
|
|
||||||
.szene-screen {
|
|
||||||
position: absolute; top: 0; left: 0; z-index: 1;
|
|
||||||
overflow: hidden; background: #fff;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
}
|
|
||||||
.szene-mb {
|
|
||||||
width: 3456px; height: 2234px;
|
|
||||||
transform: scale(var(--sk, .1707))
|
|
||||||
matrix3d(0.853327,-0.145151,0,-0.000016242,
|
|
||||||
-0.025684,1.027061,0,-0.000007324,
|
|
||||||
0,0,1,0, 1614.15,493.94,0,1);
|
|
||||||
}
|
|
||||||
/* Das iPad-Viereck stammt aus der Glasflaeche, nicht aus dem Smart-Object
|
|
||||||
des PSD: das sass zu hoch und liess unten einen dreimal so breiten
|
|
||||||
schwarzen Streifen stehen. Die Glasecken sind ueber Ausgleichsgeraden auf
|
|
||||||
den vier Kanten bestimmt und geschnitten, nicht ueber Extrempunkte: die
|
|
||||||
lagen auf den Rundungen und ergaben ein zu kleines, schiefes Viereck.
|
|
||||||
Glas 1514 x 2240 mit Eckradius 95, davon 38 px Rand nach innen, also
|
|
||||||
Display 1438 x 2164 mit Radius 57. Der Radius ist konzentrisch, aussen
|
|
||||||
minus Randbreite, damit der schwarze Rand ueberall gleich breit bleibt. */
|
|
||||||
.szene-ip {
|
|
||||||
width: 1438px; height: 2164px;
|
|
||||||
border-radius: 57px; overflow: hidden;
|
|
||||||
transform: scale(var(--sk, .1707))
|
|
||||||
matrix3d(0.852061,-0.170328,0,-0.000024605,
|
|
||||||
0.005789,0.984772,0,0.000001055,
|
|
||||||
0,0,1,0, 4244.78,536.57,0,1);
|
|
||||||
}
|
|
||||||
/* Die Aufnahme fuellt das Display randlos, wie auf einem echten Bildschirm.
|
|
||||||
Vorher stand sie als kleineres Rechteck an per Hand gemessenen
|
|
||||||
Prozentwerten darin (Breite 78,877 %, Versatz 2,715 % / 14,645 %,
|
|
||||||
abgeleitet aus einem angenommenen "groessten vollstaendig sichtbaren
|
|
||||||
Rechteck" von 2726 x 1682 bei 74/154). Zwei Fehler steckten darin:
|
|
||||||
Die Konstanten stammten nicht aus der Glasflaeche des Mockups, deshalb
|
|
||||||
blieben 656 px rechts und 470 px unten leer waehrend die Werkzeugleiste
|
|
||||||
des Boards oben unter der Deckelblende verschwand. Und Prozentwerte in
|
|
||||||
translate() beziehen sich auf die Bildkante, nicht auf das Display —
|
|
||||||
Vorschau und Export loesten sie unterschiedlich auf, die Luecke war im
|
|
||||||
Export groesser als im Canvas.
|
|
||||||
object-fit uebernimmt das jetzt: kein Versatz, der auseinanderlaufen
|
|
||||||
koennte, und die Blende beschneidet von selbst. */
|
|
||||||
.szene-screen > img {
|
|
||||||
position: absolute; top: 0; left: 0;
|
|
||||||
width: 100%; height: 100%;
|
|
||||||
object-fit: cover; object-position: center;
|
|
||||||
transform-origin: top left;
|
|
||||||
}
|
|
||||||
/* Der Hintergrundton bleibt als Rueckfall stehen, falls eine Aufnahme
|
|
||||||
einmal nicht ankommt — dann faellt es als Flaeche auf, nicht als Loch. */
|
|
||||||
.szene-mb { background: #F5F4F4; }
|
|
||||||
.szene-ip { background: #FAFAFA; }
|
|
||||||
/* Das Board wird beim Fuellen seitlich beschnitten. Was wegfaellt, soll
|
|
||||||
rechts wegfallen: dort steht ohnehin das iPad davor. */
|
|
||||||
.szene-mb > img { object-position: left center; }
|
|
||||||
|
|
||||||
.laptop-missing {
|
.laptop-missing {
|
||||||
width: 940px; padding: 80px 40px; text-align: center;
|
width: 940px; padding: 80px 40px; text-align: center;
|
||||||
@@ -1027,15 +970,15 @@
|
|||||||
const SLIDES = [
|
const SLIDES = [
|
||||||
{
|
{
|
||||||
key: "titel", type: "title",
|
key: "titel", type: "title",
|
||||||
layouts: [{ id: "klassisch", label: "Klassisch" }, { id: "wabe", label: "Wabe" }, { id: "laptop", label: "Laptop" }, { id: "laptop-logo", label: "Laptop · Logo" }, { id: "laptop-blur", label: "Laptop · Blur" }, { id: "laptop-footer", label: "Laptop · Logo unten" }, { id: "szene", label: "Szene" }],
|
layouts: [{ id: "klassisch", label: "Klassisch" }, { id: "wabe", label: "Wabe" }, { id: "laptop", label: "Laptop" }, { id: "laptop-logo", label: "Laptop · Logo" }, { id: "laptop-blur", label: "Laptop · Blur" }, { id: "laptop-footer", label: "Laptop · Logo unten" }, { id: "szene", label: "Laptop · Board" }],
|
||||||
head: 'Vom <span class="a">Handwerker</span><br>f\u00fcr Handwerker',
|
head: 'Vom <span class="a">Handwerker</span><br>f\u00fcr Handwerker',
|
||||||
sub: "Die Software, die deine Branchenprogramme nicht ersetzt, sondern verbindet.",
|
sub: "Die Software, die deine Branchenprogramme nicht ersetzt, sondern verbindet.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "projektmanagement", type: "feature",
|
key: "projektmanagement", type: "feature",
|
||||||
layouts: [{ id: "standard", label: "Standard" }],
|
layouts: [{ id: "standard", label: "Standard" }],
|
||||||
eyebrow: "Projektmanagement",
|
eyebrow: "Vertrieb",
|
||||||
head: 'Du siehst auf einen Blick,<br><span class="a">wo jeder Auftrag steht.</span>',
|
head: 'Du siehst auf einen Blick,<br><span class="a">wo alle Auftr\u00e4ge stehen.</span>',
|
||||||
body: "Projekte, Kunden, Angebote, F\u00f6rderantr\u00e4ge. Kein Suchen, kein Nachfragen, kein Zettelchaos.",
|
body: "Projekte, Kunden, Angebote, F\u00f6rderantr\u00e4ge. Kein Suchen, kein Nachfragen, kein Zettelchaos.",
|
||||||
img: "./assets/screens/pipelines.png",
|
img: "./assets/screens/pipelines.png",
|
||||||
// Nur die linke Bildhälfte: Zoom 2 bei Versatz 0 zeigt exakt den Anteil
|
// Nur die linke Bildhälfte: Zoom 2 bei Versatz 0 zeigt exakt den Anteil
|
||||||
@@ -1052,7 +995,7 @@
|
|||||||
{
|
{
|
||||||
key: "workflow-engine", type: "feature",
|
key: "workflow-engine", type: "feature",
|
||||||
layouts: [{ id: "standard", label: "Standard" }],
|
layouts: [{ id: "standard", label: "Standard" }],
|
||||||
eyebrow: "Workflow-Engine",
|
eyebrow: "Automation & KI",
|
||||||
head: '<span class="a">Wenn-dann</span><br>statt Handarbeit.',
|
head: '<span class="a">Wenn-dann</span><br>statt Handarbeit.',
|
||||||
body: "Auslöser wählen, Aktionen dranhängen, fertig. Alles automatisch und ohne eine Zeile Code.",
|
body: "Auslöser wählen, Aktionen dranhängen, fertig. Alles automatisch und ohne eine Zeile Code.",
|
||||||
img: "./assets/screens/workflow.png",
|
img: "./assets/screens/workflow.png",
|
||||||
@@ -1073,15 +1016,18 @@
|
|||||||
{
|
{
|
||||||
key: "chat", type: "feature",
|
key: "chat", type: "feature",
|
||||||
layouts: [{ id: "standard", label: "Standard" }],
|
layouts: [{ id: "standard", label: "Standard" }],
|
||||||
eyebrow: "Team-Chat",
|
eyebrow: "Chat",
|
||||||
// "automatisch seinen Kanal." misst mit Marker 933 px bei 896
|
// Zweizeilig, aber knapp: Zeile 2 misst mit Marker 880 px bei 896
|
||||||
// verfuegbaren und bricht deshalb in eine dritte Zeile. "von selbst"
|
// verfuegbaren. Ein laengeres Wort bricht sofort um.
|
||||||
// sagt dasselbe und bleibt mit 846 px in der Zeile.
|
head: 'Projekte bekommen<br>automatisch <span class="a">ihren Kanal.</span>',
|
||||||
head: 'Jedes Projekt bekommt<br>von selbst <span class="a">seinen Kanal.</span>',
|
|
||||||
body: "Foto von der Baustelle rein, alle sehen's sofort. Aus jeder Nachricht wird mit einem Klick eine Aufgabe.",
|
body: "Foto von der Baustelle rein, alle sehen's sofort. Aus jeder Nachricht wird mit einem Klick eine Aufgabe.",
|
||||||
img: "./assets/screens/chat.png",
|
img: "./assets/screens/chat.png",
|
||||||
mockW: 1030, mockAR: 1.703,
|
mockW: 1030, mockAR: 1.703,
|
||||||
imgScale: 1, imgX: "0%", imgY: "0%",
|
imgScale: 1, imgX: "0%", imgY: "0%",
|
||||||
|
// Das hinterste Blatt zeigt sonst den Form Builder bei 3,8-fachem Zoom:
|
||||||
|
// unscharf, und die Kopieren- und Papierkorb-Symbole gehören zu einem
|
||||||
|
// anderen Feature. Stattdessen der Chat im Hochformat, ungezoomt.
|
||||||
|
back: { img: "./assets/screens/chat-tablet.png", imgScale: 1, imgX: "0%", imgY: "0%" },
|
||||||
// Das Anhang-Menü zeigt, was aus einer Nachricht alles werden kann.
|
// Das Anhang-Menü zeigt, was aus einer Nachricht alles werden kann.
|
||||||
media2: {
|
media2: {
|
||||||
img: "./assets/screens/chat-menue.png",
|
img: "./assets/screens/chat-menue.png",
|
||||||
@@ -1091,7 +1037,7 @@
|
|||||||
{
|
{
|
||||||
key: "form-builder", type: "feature",
|
key: "form-builder", type: "feature",
|
||||||
layouts: [{ id: "standard", label: "Standard" }],
|
layouts: [{ id: "standard", label: "Standard" }],
|
||||||
eyebrow: "Form Builder",
|
eyebrow: "Formulare",
|
||||||
head: 'Formulare selbst bauen.<br><span class="a">Per Drag-and-drop.</span>',
|
head: 'Formulare selbst bauen.<br><span class="a">Per Drag-and-drop.</span>',
|
||||||
body: "Von der Kontaktanfrage bis zum Aufmaß mit Unterschrift vor Ort. Teil sie per Link oder QR-Code, jede Einsendung wird automatisch zu Lead, Kontakt oder Auftrag.",
|
body: "Von der Kontaktanfrage bis zum Aufmaß mit Unterschrift vor Ort. Teil sie per Link oder QR-Code, jede Einsendung wird automatisch zu Lead, Kontakt oder Auftrag.",
|
||||||
img: "./assets/screens/form-builder.png",
|
img: "./assets/screens/form-builder.png",
|
||||||
@@ -1115,7 +1061,7 @@
|
|||||||
"logo-full": { label: "Logo", size: 560, prop: "width" },
|
"logo-full": { label: "Logo", size: 560, prop: "width" },
|
||||||
"screen-logo": { label: "Logo im Screen", size: 430, prop: "width" },
|
"screen-logo": { label: "Logo im Screen", size: 430, prop: "width" },
|
||||||
"laptop": { label: "Laptop", size: 960, prop: "width" },
|
"laptop": { label: "Laptop", size: 960, prop: "width" },
|
||||||
"szene": { label: "Szene", size: 980, prop: "width" },
|
"szene": { label: "Laptop · Board", size: 720, prop: "width" },
|
||||||
"mock": { label: "Bild", size: null, prop: "width" },
|
"mock": { label: "Bild", size: null, prop: "width" },
|
||||||
"mock-2": { label: "Zweites Bild", size: null, prop: "width" },
|
"mock-2": { label: "Zweites Bild", size: null, prop: "width" },
|
||||||
"note": { label: "Notizzettel", size: null, prop: "width" },
|
"note": { label: "Notizzettel", size: null, prop: "width" },
|
||||||
@@ -1158,7 +1104,7 @@
|
|||||||
const STORE = "hivegrid.projekt." + PROJECT;
|
const STORE = "hivegrid.projekt." + PROJECT;
|
||||||
const STATE_URL = "./state/" + PROJECT + ".json";
|
const STATE_URL = "./state/" + PROJECT + ".json";
|
||||||
|
|
||||||
const STATE_V = 2;
|
const STATE_V = 3;
|
||||||
|
|
||||||
function currentState() {
|
function currentState() {
|
||||||
return {
|
return {
|
||||||
@@ -1175,16 +1121,25 @@
|
|||||||
der seinen Stand im Speicher und schreibt jede Änderung an der Datei beim
|
der seinen Stand im Speicher und schreibt jede Änderung an der Datei beim
|
||||||
nächsten Klick wieder zu. Im Ladepfad kann er das nicht. */
|
nächsten Klick wieder zu. Im Ladepfad kann er das nicht. */
|
||||||
function migrateState(d) {
|
function migrateState(d) {
|
||||||
if (!d || (d.v || 1) >= 2) return false;
|
if (!d || (d.v || 1) >= STATE_V) return false;
|
||||||
const feat = SLIDES.map((s, i) => (s.type === "feature" ? i : -1)).filter(i => i >= 0);
|
const alt = d.v || 1;
|
||||||
const ref = feat.length && Array.isArray(d.edits) ? (d.edits[feat[0]] || {}).badge : null;
|
if (alt < 2) {
|
||||||
if (ref) {
|
const feat = SLIDES.map((s, i) => (s.type === "feature" ? i : -1)).filter(i => i >= 0);
|
||||||
for (const i of feat.slice(1)) {
|
const ref = feat.length && Array.isArray(d.edits) ? (d.edits[feat[0]] || {}).badge : null;
|
||||||
const e = d.edits[i] || (d.edits[i] = {});
|
if (ref) {
|
||||||
e.badge = Object.assign({}, e.badge, { dx: ref.dx || 0, dy: ref.dy || 0 });
|
for (const i of feat.slice(1)) {
|
||||||
|
const e = d.edits[i] || (d.edits[i] = {});
|
||||||
|
e.badge = Object.assign({}, e.badge, { dx: ref.dx || 0, dy: ref.dy || 0 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.v = 2;
|
// Stand 3: Das Titel-Mockup ist ein anderes Bild mit anderem Format
|
||||||
|
// geworden. Breite und Versatz von vorher passen dazu nicht mehr und
|
||||||
|
// wuerden das Geraet ueber die Slide hinaus schieben.
|
||||||
|
if (alt < 3 && Array.isArray(d.edits)) {
|
||||||
|
for (const e of d.edits) { if (e) delete e.szene; }
|
||||||
|
}
|
||||||
|
d.v = STATE_V;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1426,16 +1381,10 @@
|
|||||||
}
|
}
|
||||||
const logo = variant === "dunkel" ? assets["./assets/brand/logo-white.svg"] : assets["./assets/brand/logo.svg"];
|
const logo = variant === "dunkel" ? assets["./assets/brand/logo-white.svg"] : assets["./assets/brand/logo.svg"];
|
||||||
if (layoutState[i] === "szene") {
|
if (layoutState[i] === "szene") {
|
||||||
const dev = assets["./assets/mockups/macbook-szene.png"]
|
const dev = assets["./assets/mockups/macbook-board.png"]
|
||||||
? '<div class="szene">' +
|
? '<div class="szene"><img class="szene-dev" alt="" src="' +
|
||||||
'<div class="szene-screen szene-mb"><img alt="" src="' +
|
assets["./assets/mockups/macbook-board.png"] + '"></div>'
|
||||||
assets["./assets/screens/pipelines.png"] + '"></div>' +
|
: '<div class="laptop-missing">Mockup fehlt.<br>Das freigestellte PNG als <b>assets/mockups/macbook-board.png</b> ablegen.</div>';
|
||||||
'<div class="szene-screen szene-ip"><img alt="" src="' +
|
|
||||||
assets["./assets/screens/chat-tablet.png"] + '"></div>' +
|
|
||||||
'<img class="szene-dev" alt="" src="' +
|
|
||||||
assets["./assets/mockups/macbook-szene.png"] + '">' +
|
|
||||||
'</div>'
|
|
||||||
: '<div class="laptop-missing">Szenen-Mockup fehlt.<br>Das freigestellte PNG als <b>assets/mockups/macbook-szene.png</b> ablegen.</div>';
|
|
||||||
return '<div class="title-top">' +
|
return '<div class="title-top">' +
|
||||||
'<p class="wabe-tagline">Vom Handwerker<br>für <span class="a">Handwerker</span></p>' +
|
'<p class="wabe-tagline">Vom Handwerker<br>für <span class="a">Handwerker</span></p>' +
|
||||||
'<img class="wabe-logo" alt="HiveGrid" src="' + logo + '">' +
|
'<img class="wabe-logo" alt="HiveGrid" src="' + logo + '">' +
|
||||||
@@ -1527,20 +1476,8 @@
|
|||||||
e.size ? e.size + "px" : "";
|
e.size ? e.size + "px" : "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Die Perspektiv-Matrizen der Szene rechnen in Bildpixeln des Originals.
|
|
||||||
// Der Faktor auf die Breite in der Slide haengt also an der Geraetebreite
|
|
||||||
// und muss jede Groessenaenderung mitmachen.
|
|
||||||
const sz = slideEl.querySelector(".szene");
|
|
||||||
if (sz) {
|
|
||||||
const w = (set["szene"] || {}).size || STANDARD["szene"].size;
|
|
||||||
sz.style.setProperty("--sk", w / SZENE_PX);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Breite des freigestellten Mockups im Originalmassstab. Die matrix3d-Werte
|
|
||||||
// sind darauf bezogen, deshalb steht die Zahl hier und nicht im CSS.
|
|
||||||
const SZENE_PX = 5742;
|
|
||||||
|
|
||||||
// Eine Seite = der Inhalt genau einer Slide, unabhängig davon, in welcher
|
// Eine Seite = der Inhalt genau einer Slide, unabhängig davon, in welcher
|
||||||
// Slide sie gerade mitgerendert wird.
|
// Slide sie gerade mitgerendert wird.
|
||||||
function buildPage(j) {
|
function buildPage(j) {
|
||||||
@@ -1560,9 +1497,14 @@
|
|||||||
if (sl.mockW) mock.style.setProperty("--mock-w", sl.mockW + "px");
|
if (sl.mockW) mock.style.setProperty("--mock-w", sl.mockW + "px");
|
||||||
if (sl.mockAR) mock.style.setProperty("--mock-ar", sl.mockAR);
|
if (sl.mockAR) mock.style.setProperty("--mock-ar", sl.mockAR);
|
||||||
if (sl.mockLeft) mock.style.setProperty("--mock-left", sl.mockLeft + "px");
|
if (sl.mockLeft) mock.style.setProperty("--mock-left", sl.mockLeft + "px");
|
||||||
// Hinterstes Blatt bekommt den Screen der nächsten Feature-Slide.
|
/* Hinterstes Blatt bekommt standardmässig den Screen der nächsten
|
||||||
|
Feature-Slide. Das kann danebengehen: der nächste Screen ist
|
||||||
|
womöglich stark gezoomt und damit unscharf, und er zeigt Bedienung,
|
||||||
|
die zum Feature dieser Slide gar nicht passt. Deshalb ist er über
|
||||||
|
"back" pro Slide überschreibbar. */
|
||||||
const withImg = SLIDES.filter(x => x.img);
|
const withImg = SLIDES.filter(x => x.img);
|
||||||
const other = withImg[(withImg.findIndex(x => x.img === sl.img) + 1) % withImg.length];
|
const auto = withImg[(withImg.findIndex(x => x.img === sl.img) + 1) % withImg.length];
|
||||||
|
const other = sl.back || { img: auto.img, imgScale: auto.imgScale, imgX: auto.imgX, imgY: auto.imgY };
|
||||||
mock.innerHTML =
|
mock.innerHTML =
|
||||||
'<div class="sheet-back"><img alt="" src="' + assets[other.img] +
|
'<div class="sheet-back"><img alt="" src="' + assets[other.img] +
|
||||||
'" style="transform:scale(' + other.imgScale + ') translate(' +
|
'" style="transform:scale(' + other.imgScale + ') translate(' +
|
||||||
@@ -1695,11 +1637,12 @@
|
|||||||
async function preloadAssets() {
|
async function preloadAssets() {
|
||||||
const paths = ["./assets/brand/logo.svg", "./assets/brand/logo-white.svg"]
|
const paths = ["./assets/brand/logo.svg", "./assets/brand/logo-white.svg"]
|
||||||
.concat(SLIDES.filter(s => s.img).map(s => s.img))
|
.concat(SLIDES.filter(s => s.img).map(s => s.img))
|
||||||
|
.concat(SLIDES.filter(s => s.back).map(s => s.back.img))
|
||||||
.concat(SLIDES.filter(s => s.media2).map(s => s.media2.img));
|
.concat(SLIDES.filter(s => s.media2).map(s => s.media2.img));
|
||||||
paths.push("./assets/screens/pipelines.png", "./assets/screens/chat-tablet.png");
|
paths.push("./assets/screens/pipelines.png", "./assets/screens/chat-tablet.png");
|
||||||
// Optional: the layout falls back to a hint if the file is not there yet.
|
// Optional: the layout falls back to a hint if the file is not there yet.
|
||||||
const optional = new Set(["./assets/mockups/laptop.png", "./assets/mockups/macbook-szene.png"]);
|
const optional = new Set(["./assets/mockups/laptop.png", "./assets/mockups/macbook-board.png"]);
|
||||||
paths.push("./assets/mockups/laptop.png", "./assets/mockups/macbook-szene.png");
|
paths.push("./assets/mockups/laptop.png", "./assets/mockups/macbook-board.png");
|
||||||
for (const path of [...new Set(paths)]) {
|
for (const path of [...new Set(paths)]) {
|
||||||
const res = await fetch(path, { cache: "no-store" }).catch(() => null);
|
const res = await fetch(path, { cache: "no-store" }).catch(() => null);
|
||||||
if (!res || !res.ok) {
|
if (!res || !res.ok) {
|
||||||
@@ -1851,7 +1794,7 @@
|
|||||||
Geräterahmen selbst. Die Rahmen fehlten in dieser Liste, deshalb blieb ein
|
Geräterahmen selbst. Die Rahmen fehlten in dieser Liste, deshalb blieb ein
|
||||||
Export ohne Macbook unbemerkt. */
|
Export ohne Macbook unbemerkt. */
|
||||||
const SHOT_BOXES =
|
const SHOT_BOXES =
|
||||||
".mock-inner, .laptop-screen, .hex-shot, .szene-screen, .szene-dev, .laptop-frame";
|
".mock-inner, .laptop-screen, .hex-shot, .szene-dev, .laptop-frame";
|
||||||
const MAX_TRIES = 5;
|
const MAX_TRIES = 5;
|
||||||
// Ab hier gilt eine Fläche als leer. Da nur noch das Innere des Vierecks
|
// Ab hier gilt eine Fläche als leer. Da nur noch das Innere des Vierecks
|
||||||
// abgetastet wird, ist kein Beiwerk mehr dabei, das die Spanne aufbläht.
|
// abgetastet wird, ist kein Beiwerk mehr dabei, das die Spanne aufbläht.
|
||||||
@@ -1859,9 +1802,9 @@
|
|||||||
|
|
||||||
/* Die vier Ecken eines Kindes in Slide-Koordinaten.
|
/* Die vier Ecken eines Kindes in Slide-Koordinaten.
|
||||||
Vorher stand hier das achsenparallele Umrechteck. Das war der Fehler:
|
Vorher stand hier das achsenparallele Umrechteck. Das war der Fehler:
|
||||||
.szene-mb und .szene-ip stehen per matrix3d schräg im Raum, ihr Umrechteck
|
ein gedrehtes oder perspektivisch gestelltes Bild hat ein Umrechteck, das
|
||||||
umfasst Raster, Hintergrund und das Nachbargerät. Darin fand die Prüfung
|
Raster, Hintergrund und Nachbarelemente mit einschliesst. Darin fand die
|
||||||
immer genug Helligkeitsspanne und winkte eine leere Displayfläche durch —
|
Prüfung immer genug Helligkeitsspanne und winkte eine leere Fläche durch —
|
||||||
genau so kam ein Export ohne Screenshots durch die Kontrolle.
|
genau so kam ein Export ohne Screenshots durch die Kontrolle.
|
||||||
getBoxQuads gäbe die echten Ecken, kennt Chrome aber nicht. Also werden
|
getBoxQuads gäbe die echten Ecken, kennt Chrome aber nicht. Also werden
|
||||||
vier 1-px-Marken in die Ecken gesetzt und ausgemessen: die Layout-Engine
|
vier 1-px-Marken in die Ecken gesetzt und ausgemessen: die Layout-Engine
|
||||||
|
|||||||
+6
-11
@@ -34,11 +34,6 @@
|
|||||||
"dx": -40,
|
"dx": -40,
|
||||||
"dy": 597
|
"dy": 597
|
||||||
},
|
},
|
||||||
"szene": {
|
|
||||||
"dx": 1,
|
|
||||||
"dy": -88,
|
|
||||||
"size": 1020
|
|
||||||
},
|
|
||||||
"wabe-claim": {
|
"wabe-claim": {
|
||||||
"dx": 4,
|
"dx": 4,
|
||||||
"dy": -891
|
"dy": -891
|
||||||
@@ -67,7 +62,7 @@
|
|||||||
},
|
},
|
||||||
"mock": {
|
"mock": {
|
||||||
"dx": 96,
|
"dx": 96,
|
||||||
"dy": 18,
|
"dy": 15,
|
||||||
"size": 706
|
"size": 706
|
||||||
},
|
},
|
||||||
"mock-2": {
|
"mock-2": {
|
||||||
@@ -91,7 +86,7 @@
|
|||||||
},
|
},
|
||||||
"mock": {
|
"mock": {
|
||||||
"dx": -36,
|
"dx": -36,
|
||||||
"dy": -371,
|
"dy": -357,
|
||||||
"size": 965
|
"size": 965
|
||||||
},
|
},
|
||||||
"mock-2": {
|
"mock-2": {
|
||||||
@@ -120,7 +115,7 @@
|
|||||||
},
|
},
|
||||||
"mock": {
|
"mock": {
|
||||||
"dx": -20,
|
"dx": -20,
|
||||||
"dy": -232,
|
"dy": -222,
|
||||||
"size": 931
|
"size": 931
|
||||||
},
|
},
|
||||||
"mock-2": {
|
"mock-2": {
|
||||||
@@ -143,12 +138,12 @@
|
|||||||
},
|
},
|
||||||
"mock": {
|
"mock": {
|
||||||
"dx": -24,
|
"dx": -24,
|
||||||
"dy": 0,
|
"dy": -8,
|
||||||
"size": 584
|
"size": 584
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"frameStyle": "stapel",
|
"frameStyle": "rund",
|
||||||
"layoutState": [
|
"layoutState": [
|
||||||
"szene",
|
"szene",
|
||||||
"standard",
|
"standard",
|
||||||
@@ -159,7 +154,7 @@
|
|||||||
"superSample": 3,
|
"superSample": 3,
|
||||||
"tagOut": "an",
|
"tagOut": "an",
|
||||||
"tilt": "aus",
|
"tilt": "aus",
|
||||||
"v": 2,
|
"v": 3,
|
||||||
"variant": "hell",
|
"variant": "hell",
|
||||||
"view": "streifen"
|
"view": "streifen"
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user