LED wall active area: confine the output to a pixel-mapping rectangle

New 'Area LED' controls in the Schermo tab: W x H @ X,Y. Everything
(canvas, videos, images, logos, ticker) lives in a #stage box whose
transform makes it the containing block for the fixed layers, so resizing
it confines the whole show at once, black outside. The canvas resizes to
the stage, so shaders render at the wall's native resolution. Persisted
in localStorage and re-pushed when the output window (re)starts; the
recorder follows the canvas position.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
lucianoandClaude Fable 5 committed 2026-07-30 10:41:23 +02:00
1 parent c1b3f9c311
commit de85639aaf
6 files changed
+80 -8

No files matched your search

+16 -1
View File
@@ -83,7 +83,9 @@ function composeFrame() {
recCtx.globalAlpha = 1;
recCtx.globalCompositeOperation = 'source-over';
recCtx.clearRect(0, 0, W, H);
recCtx.drawImage(canvas, 0, 0, W, H);
// Draw the canvas where it actually sits (the LED area may confine it).
const cr = canvas.getBoundingClientRect();
recCtx.drawImage(canvas, cr.x * sx, cr.y * sy, cr.width * sx, cr.height * sy);
if (bgVideo.classList.contains('show') && bgVideo.readyState >= 2 && bgVideo.videoWidth) {
recCtx.globalAlpha = parseFloat(getComputedStyle(bgVideo).opacity) || 1;
@@ -318,6 +320,19 @@ djv.onControl(async (m) => {
djv.report({ type: 'autoVj', on: autoVj });
break;
case 'svg': loadCustomTexture(m.dataUrl); break;
case 'ledArea': {
// Confine the whole show to a W×H rectangle at X,Y (LED pixel mapping).
const st = $('#stage').style;
if (m.on && m.w > 0 && m.h > 0) {
st.left = (m.x || 0) + 'px'; st.top = (m.y || 0) + 'px';
st.width = m.w + 'px'; st.height = m.h + 'px';
} else {
st.left = st.top = '0px';
st.width = st.height = '';
}
viz.resize();
break;
}
case 'recStart': startRecording(m); break;
case 'recStop': stopRecording(m); break;
case 'gain': audio.gain = m.value; break;