Lay the party logo over the background

Centred, spanning 60% of the screen width, on the poster's layer so the
video frame and the stills still pass in front of it. The file lives in
assets/ with the posters, so it has to be kept out of the background
rotation — it is the one image there that is never a background.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9v2Xoa6eoeGYpK6gp95k9
This commit is contained in:
simon
2026-08-10 23:46:19 +02:00
co-authored by Claude Opus 5
parent 0683acd69e
commit 7706fe46c6
6 changed files with 47 additions and 2 deletions
+13
View File
@@ -17,11 +17,24 @@ import {
BACKGROUND_MAX_ZOOM,
BACKGROUND_FOCUS_SPREAD,
BACKGROUND_MAX_OVERSAMPLE,
LOGO_SRC,
LOGO_WIDTH,
} from '/config.js';
import { createPicker } from './motion.js';
const KEYS = Object.keys(BACKGROUNDS);
/**
* Point the logo overlay at the configured file and size it against the
* screen. The element is in the page from the start — only the two values that
* belong to the config are set here.
*/
export function showLogo(element) {
if (!element) return;
element.src = LOGO_SRC;
element.style.width = `${LOGO_WIDTH * 100}vw`;
}
/**
* A zoom level and the point of the image the crop closes in on, in percent.
* The focal point is pulled toward the middle by BACKGROUND_FOCUS_SPREAD, so a
+4
View File
@@ -9,6 +9,10 @@
<body>
<div id="backgrounds"></div>
<!-- The party's logo, centred over the poster. Its src and width come from
the shared config, so the file can be swapped without touching this. -->
<img id="logo" alt="" />
<!-- Frozen screenshots of the frame. A sibling, not a child, of #frameMover:
these are positioned against the screen, not the moving frame. -->
<div id="stills"></div>
+17
View File
@@ -42,6 +42,23 @@ body {
opacity: 1;
}
/* The logo sits on the poster, not on the video: it shares the backdrop's
layer so the frame and the stills still pass in front of it. Its width comes
from LOGO_WIDTH, written onto the element by backdrop.js. */
#logo {
position: fixed;
top: 50%;
left: 50%;
translate: -50% -50%;
height: auto;
/* Only bites on a screen too short for the width above — on the projector
the width is what decides. */
max-height: 70vh;
object-fit: contain;
pointer-events: none;
z-index: 0;
}
/* Built and removed by the wash animation. Sits between the poster and the
stills, and blends rather than covers, so the poster stays legible through
whatever colour is passing over it. The gradient itself is written per frame
+3 -1
View File
@@ -2,7 +2,7 @@ import { connect } from '/shared/socket.js';
import { OVERLAP_SECONDS, HARD_CUT_SECONDS, AUTO_BACKGROUND, AUTO_ANIMATION } from '/config.js';
import { createPlayer, loadApi, STATE } from './yt.js';
import { startAnimationCycle } from './motion.js';
import { startBackgroundCycle } from './backdrop.js';
import { startBackgroundCycle, showLogo } from './backdrop.js';
import { requestCapture } from './capture.js';
const TICK_MS = 250;
@@ -25,6 +25,8 @@ const backgrounds = startBackgroundCycle(
state.background,
);
showLogo(document.getElementById('logo'));
// --- start gate ---------------------------------------------------------
const gate = document.getElementById('gate');