mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-08-15 05:04:42 +08:00
fix(backlot): keep storyboard beside decisions rail; portrait-aware render player
- Storyboard, found-media, and renders sections now render inside the main column instead of after the .board grid, so a tall decisions rail no longer pushes them below the fold (they flow beside the rail). - Render hero player: preload=metadata so the video has its intrinsic aspect ratio (and a poster frame) before playback, and natural-width centering so a 9:16 render displays as a portrait frame instead of a letterboxed landscape box. Degraded (no-grid) view keeps the old full-width flow.
This commit is contained in:
@@ -505,8 +505,10 @@ a.backlink:hover { color: var(--text-2); }
|
||||
}
|
||||
|
||||
/* render section */
|
||||
.render-hero { position: relative; border-radius: 12px; overflow: hidden; border: 1px solid var(--border); background: #000; }
|
||||
.render-hero video { width: 100%; display: block; max-height: 560px; }
|
||||
.render-hero { position: relative; border-radius: 12px; overflow: hidden; border: 1px solid var(--border); background: #000; display: flex; justify-content: center; }
|
||||
/* natural width up to the container: a 9:16 render shows as a centered
|
||||
portrait frame instead of stretching into a letterboxed landscape box */
|
||||
.render-hero video { display: block; width: auto; max-width: 100%; max-height: 560px; }
|
||||
.render-meta { font-family: var(--mono); font-size: calc(10.5px * var(--fs-scale)); color: var(--text-3); padding: 8px 2px; display: flex; gap: 14px; flex-wrap: wrap; }
|
||||
.render-meta .v { color: var(--text-2); cursor: pointer; }
|
||||
.render-meta .v.active { color: var(--amber); }
|
||||
|
||||
@@ -528,7 +528,10 @@ function renderRenders(s) {
|
||||
// watch: carry playback position/state over to the recreated element.
|
||||
const prev = document.querySelector(".render-hero video");
|
||||
const src = mediaURL(s.project_id, current.path);
|
||||
const video = el("video", { src, controls: "", preload: "none" });
|
||||
// preload="metadata" gives the element its intrinsic aspect ratio (and a
|
||||
// poster frame) before playback — without it a portrait 9:16 render sits
|
||||
// in a letterboxed 100%-wide black box that reads as landscape.
|
||||
const video = el("video", { src, controls: "", preload: "metadata" });
|
||||
// Click the frame to start playback (controls handle pause/scrub) — the
|
||||
// big player was inert to a click on the picture itself.
|
||||
video.addEventListener("click", () => { if (video.paused) video.play().catch(() => {}); });
|
||||
@@ -778,16 +781,22 @@ function render() {
|
||||
if (decisions) aside.append(decisions);
|
||||
if (activity) aside.append(activity);
|
||||
|
||||
if (script || decisions || activity) {
|
||||
app.append(el("div", { class: "board" }, main, aside));
|
||||
}
|
||||
|
||||
// Media sections live INSIDE the main column so a tall decisions rail
|
||||
// never pushes them below the fold — the column flows beside the rail.
|
||||
const storyboard = renderStoryboard(s);
|
||||
if (storyboard) app.append(storyboard);
|
||||
const found = renderFoundMedia(s);
|
||||
if (found) app.append(found);
|
||||
const renders = renderRenders(s);
|
||||
if (renders) app.append(renders);
|
||||
|
||||
if (script || decisions || activity) {
|
||||
for (const section of [storyboard, found, renders]) {
|
||||
if (section) main.append(section);
|
||||
}
|
||||
app.append(el("div", { class: "board" }, main, aside));
|
||||
} else {
|
||||
for (const section of [storyboard, found, renders]) {
|
||||
if (section) app.append(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Defensive normalization (F-02): the server contract guarantees these
|
||||
|
||||
Reference in New Issue
Block a user