This commit is contained in:
2026-09-16 05:50:50 +02:00
parent a7c3a5e472
commit fdb684e96f
2 changed files with 176 additions and 39 deletions
+30 -5
View File
@@ -14,6 +14,7 @@
--gray: #262626;
--accent: #9f0;
--accent-rgb: 153, 255, 0;
--sidebar-w: 300px;
--emoji-fav-color: #f5c518;
--nav-bg: #2b2b2b;
--nav-brand-border: inset 1px #242424;
@@ -10388,19 +10389,43 @@ div.favs div.posts {
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
width: calc(100vw - var(--sidebar-w, 300px));
height: 100%;
transform: translate3d(0, 0, 0) scale(var(--bg-canvas-zoom, 1.12));
transform-origin: center center;
z-index: -2;
transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1);
transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1), width 0.3s ease-in-out;
opacity: var(--bg-canvas-opacity, 1.0);
filter: var(--bg-canvas-filter, none);
-webkit-filter: var(--bg-canvas-filter, none);
background-color: var(--bg-canvas-color, transparent);
}
body.sidebar-right-hidden,
body:not(:has(.global-sidebar-right)):not(:has(.item-sidebar-right)):not(:has(.index-sidebar-right)) {
--sidebar-w: 0px !important;
}
body.sidebar-right-hidden #bg,
body:not(:has(.global-sidebar-right)):not(:has(.item-sidebar-right)):not(:has(.index-sidebar-right)) #bg {
width: 100vw !important;
}
@media (min-width: 600px) and (max-width: 999px) {
:root {
--sidebar-w: min(280px, 80vw);
}
}
@media (max-width: 599px) {
:root {
--sidebar-w: 0px !important;
}
#bg {
width: 100vw !important;
}
}
button#togglebg {
display: inline;
cursor: pointer;
@@ -20863,7 +20888,7 @@ body.onara-modal-open #bg.fader-out,
body.onara-modal-open #bg.fast-fade {
z-index: 51 !important;
cursor: pointer !important;
transition: none !important;
transition: width 0.3s ease-in-out !important;
animation: none !important;
opacity: var(--bg-canvas-opacity, 1.0) !important;
}
@@ -20916,7 +20941,7 @@ body.onara-modal-open .admin-bar.open {
top: var(--navbar-h, 50px) !important;
bottom: 0 !important;
left: 0 !important;
right: 300px !important;
right: var(--sidebar-w, 300px) !important;
width: auto !important;
height: calc(100vh - var(--navbar-h, 50px)) !important;
z-index: 10050 !important;
+143 -31
View File
@@ -2628,6 +2628,38 @@ window.cancelAnimFrame = (function () {
initialCanvas.classList.add('fader-out');
initialCanvas.classList.remove('fader-in');
}
// Live-sync #bg canvas backing store dimensions and redraw when free space changes (sidebar toggle, resize, etc.)
if (window.ResizeObserver) {
let _bgResizeTimer = null;
let _lastBgW = 0;
let _lastBgH = 0;
const _bgObserver = new ResizeObserver((entries) => {
const entry = entries && entries[0];
const cr = entry ? entry.contentRect : initialCanvas.getBoundingClientRect();
const curW = Math.round(cr.width);
const curH = Math.round(cr.height);
if (Math.abs(curW - _lastBgW) <= 2 && Math.abs(curH - _lastBgH) <= 2) return;
_lastBgW = curW;
_lastBgH = curH;
if (_bgResizeTimer) clearTimeout(_bgResizeTimer);
_bgResizeTimer = setTimeout(() => {
if (typeof window.redrawBgCanvas === 'function') {
window.redrawBgCanvas();
} else if (typeof window.initBackground === 'function') {
window.initBackground();
}
}, 50);
});
_bgObserver.observe(initialCanvas);
} else {
window.addEventListener('resize', () => {
if (typeof window.redrawBgCanvas === 'function') {
window.redrawBgCanvas();
}
}, { passive: true });
}
}
@@ -4137,6 +4169,10 @@ window.cancelAnimFrame = (function () {
canvas._bgFadingOut = false;
canvas.classList.add('fader-in');
canvas.classList.remove('fader-out', 'fast-fade');
if (document.body.classList.contains('onara-modal-open')) {
canvas.style.transition = 'none';
canvas.style.opacity = 'var(--bg-canvas-opacity, 1.0)';
}
} else {
// Don't clear the canvas here — let the existing content fade out.
canvas._bgFadingOut = true;
@@ -4153,8 +4189,17 @@ window.cancelAnimFrame = (function () {
}
const SCALE = 0.5;
const cw = Math.max(1, (canvas.clientWidth * SCALE) | 0);
const ch = Math.max(1, (canvas.clientHeight * SCALE) | 0);
const syncCanvasDimensions = () => {
const curCw = Math.max(1, (canvas.clientWidth * SCALE) | 0);
const curCh = Math.max(1, (canvas.clientHeight * SCALE) | 0);
if (canvas.width !== curCw || canvas.height !== curCh) {
canvas.width = curCw;
canvas.height = curCh;
}
return { w: canvas.width, h: canvas.height };
};
const { w: cw, h: ch } = syncCanvasDimensions();
// Capture previous canvas snapshot for buttery-smooth crossfade transition
let prevSnapshot = null;
@@ -4170,11 +4215,6 @@ window.cancelAnimFrame = (function () {
}
}
if (canvas.width !== cw || canvas.height !== ch) {
canvas.width = cw;
canvas.height = ch;
}
const context = canvas.getContext('2d');
const cfgCurrent = window.audioVisualizerTuning || DEFAULT_AUDIO_TUNING;
const blurSetting = cfgCurrent.bgCanvasBlur !== undefined ? Number(cfgCurrent.bgCanvasBlur) : 30;
@@ -4200,6 +4240,8 @@ window.cancelAnimFrame = (function () {
const drawCoverImage = (ctx, source) => {
if (!source) return;
const targetCw = (ctx && ctx.canvas) ? ctx.canvas.width : canvas.width;
const targetCh = (ctx && ctx.canvas) ? ctx.canvas.height : canvas.height;
let sw = 0, sh = 0;
if (source.videoWidth && source.videoHeight) {
sw = source.videoWidth;
@@ -4216,14 +4258,14 @@ window.cancelAnimFrame = (function () {
}
if (sw > 0 && sh > 0) {
const scale = Math.max(cw / sw, ch / sh);
const scale = Math.max(targetCw / sw, targetCh / sh);
const dw = sw * scale;
const dh = sh * scale;
const dx = (cw - dw) / 2;
const dy = (ch - dh) / 2;
const dx = (targetCw - dw) / 2;
const dy = (targetCh - dh) / 2;
ctx.drawImage(source, dx, dy, dw, dh);
} else {
ctx.drawImage(source, 0, 0, cw, ch);
ctx.drawImage(source, 0, 0, targetCw, targetCh);
}
};
@@ -4242,13 +4284,17 @@ window.cancelAnimFrame = (function () {
let crossfadeRafId = null;
const crossfadeToSource = (sourceImg, onComplete) => {
if (crossfadeRafId) window.cancelAnimFrame(crossfadeRafId);
if (!prevSnapshot) {
context.clearRect(0, 0, cw, ch);
syncCanvasDimensions();
const targetW = canvas.width;
const targetH = canvas.height;
const isOnara = document.body.classList.contains('onara-modal-open') || (typeof isOnaraActive === 'function' && isOnaraActive());
if (!prevSnapshot || isOnara) {
context.clearRect(0, 0, targetW, targetH);
context.save();
context.filter = getCanvasFilter();
drawCoverImage(context, sourceImg);
context.restore();
applyBgColorOverlay(context, cw, ch);
applyBgColorOverlay(context, targetW, targetH);
if (onComplete) onComplete();
return;
}
@@ -4261,13 +4307,16 @@ window.cancelAnimFrame = (function () {
const progress = Math.min(1.0, elapsed / duration);
const ease = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
context.clearRect(0, 0, cw, ch);
syncCanvasDimensions();
const w = canvas.width;
const h = canvas.height;
context.clearRect(0, 0, w, h);
// 1. Fade out previous background
if (ease < 1.0 && prevSnapshot) {
context.save();
context.globalAlpha = 1.0 - ease;
context.drawImage(prevSnapshot, 0, 0, cw, ch);
context.drawImage(prevSnapshot, 0, 0, w, h);
context.restore();
}
@@ -4281,7 +4330,7 @@ window.cancelAnimFrame = (function () {
context.restore();
// 3. Color overlay tint if configured
applyBgColorOverlay(context, cw, ch);
applyBgColorOverlay(context, w, h);
if (progress < 1.0) {
crossfadeRafId = window.requestAnimFrame(step);
@@ -4296,10 +4345,23 @@ window.cancelAnimFrame = (function () {
const drawOnce = () => {
if (!background || !context) return;
syncCanvasDimensions();
const itemId = window.getCurrentItemId();
const isDrawable = elem && elem.tagName === 'IMG';
if (itemId) {
if (document.body.classList.contains('onara-modal-open')) {
const onaraThumbImg = document.querySelector('.posts > a.thumb.onara-active img, .posts > a.thumb:focus img');
if (onaraThumbImg && onaraThumbImg.complete && onaraThumbImg.naturalWidth > 0) {
crossfadeToSource(onaraThumbImg, () => {
if (isDrawable && elem.complete && elem.naturalWidth > 0) {
crossfadeToSource(elem);
}
});
return;
}
}
const thumb = new Image();
thumb.onload = () => {
crossfadeToSource(thumb, () => {
@@ -4341,8 +4403,12 @@ window.cancelAnimFrame = (function () {
return;
}
try {
context.clearRect(0, 0, cw, ch);
if (prevSnapshot) {
syncCanvasDimensions();
const curCw = canvas.width;
const curCh = canvas.height;
context.clearRect(0, 0, curCw, curCh);
const isOnara = document.body.classList.contains('onara-modal-open') || (typeof isOnaraActive === 'function' && isOnaraActive());
if (prevSnapshot && !isOnara) {
const elapsed = performance.now() - videoFadeStartTime;
const progress = Math.min(1.0, elapsed / 350);
const ease = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
@@ -4350,7 +4416,7 @@ window.cancelAnimFrame = (function () {
if (ease < 1.0) {
context.save();
context.globalAlpha = 1.0 - ease;
context.drawImage(prevSnapshot, 0, 0, cw, ch);
context.drawImage(prevSnapshot, 0, 0, curCw, curCh);
context.restore();
}
@@ -4366,7 +4432,7 @@ window.cancelAnimFrame = (function () {
prevSnapshot = null;
}
} else {
// Video already loaded or resumed from pause: render directly at 100% opacity without fading from black
// Video already loaded or resumed from pause (or instant in Onara): render directly at 100% opacity without fading from black
context.save();
context.filter = getCanvasFilter();
try {
@@ -4376,7 +4442,7 @@ window.cancelAnimFrame = (function () {
}
// Color overlay tint if configured
applyBgColorOverlay(context, cw, ch);
applyBgColorOverlay(context, curCw, curCh);
} catch (e) {
bgRafId = null;
return;
@@ -4439,8 +4505,8 @@ window.cancelAnimFrame = (function () {
if (bgRafId) window.cancelAnimFrame(bgRafId);
animationLoop();
}
// For album videos that haven't started yet, drawOnce with the thumbnail
else if (isAlbumVideo) {
// For album videos that haven't started yet, or Onara videos pending play, drawOnce with the thumbnail
else if (isAlbumVideo || document.body.classList.contains('onara-modal-open')) {
drawOnce();
}
}
@@ -8622,11 +8688,8 @@ window.cancelAnimFrame = (function () {
const srcH = innerEyeCanvas.height;
const bgScale = cfg.bgCanvasScale !== undefined ? Number(cfg.bgCanvasScale) : 3;
// Measure the sidebar so we center within the content area, not the full viewport
const sidebar = document.querySelector('.global-sidebar-right');
const sidebarW = (sidebar && !document.body.classList.contains('sidebar-right-hidden'))
? (sidebar.offsetWidth || 0) * SCALE : 0;
const contentW = bw - sidebarW;
// #bg canvas is already positioned to the free space respecting the sidebar
const contentW = bw;
const fitScale = Math.min(contentW / srcW, bh / srcH);
const dw = srcW * fitScale * bgScale;
@@ -9213,6 +9276,9 @@ window.cancelAnimFrame = (function () {
w.style.removeProperty('padding-right');
w.style.removeProperty('right');
});
if (typeof window.redrawBgCanvas === 'function') {
window.redrawBgCanvas();
}
});
};
mq.addEventListener('change', applyBreakpoint);
@@ -10310,14 +10376,22 @@ window.cancelAnimFrame = (function () {
document.querySelectorAll('video:not(#gchat-messages video), audio:not(#gchat-messages audio)').forEach(el => { try { el.pause(); } catch {} });
}
// Fade out background canvas for smooth transition
// Fade out background canvas for smooth transition (non-Onara only)
const canvas = document.getElementById('bg');
if (canvas) {
if (useOnara) {
canvas._bgFadingOut = false;
canvas.classList.remove('fader-out', 'fast-fade');
canvas.classList.add('fader-in');
canvas.style.transition = 'none';
canvas.style.opacity = 'var(--bg-canvas-opacity, 1.0)';
} else {
canvas.classList.add('fast-fade');
canvas.classList.remove('fader-in');
canvas.classList.add('fader-out');
}
}
}
// Show loading indicator
if (navbar && !options.keepMedia) navbar.classList.add("pbwork");
@@ -10622,7 +10696,14 @@ window.cancelAnimFrame = (function () {
if (!options.keepMedia) {
setupMedia();
const _canvas = document.getElementById('bg');
if (_canvas) _canvas.classList.remove('fader-out', 'fast-fade');
if (_canvas) {
_canvas.classList.remove('fader-out', 'fast-fade');
_canvas.classList.add('fader-in');
if (useOnara) {
_canvas.style.transition = 'none';
_canvas.style.opacity = 'var(--bg-canvas-opacity, 1.0)';
}
}
if (window.initBackground) window.initBackground();
if (window.initVisualizer) window.initVisualizer();
}
@@ -10891,6 +10972,11 @@ window.cancelAnimFrame = (function () {
const canvas = document.getElementById('bg');
if (canvas) {
canvas.classList.remove('fader-out', 'fast-fade');
canvas.classList.add('fader-in');
if (useOnara) {
canvas.style.transition = 'none';
canvas.style.opacity = 'var(--bg-canvas-opacity, 1.0)';
}
}
if (window.initBackground) window.initBackground();
if (window.initVisualizer) window.initVisualizer();
@@ -11040,6 +11126,10 @@ window.cancelAnimFrame = (function () {
if (document.activeElement && document.activeElement !== thumbnail && typeof document.activeElement.blur === 'function') {
document.activeElement.blur();
}
openOnaraModal();
if (typeof window.paintImmediateBgThumb === 'function') {
window.paintImmediateBgThumb(thumbnail);
}
}
// Thumbnails inherit context (e.g. from Tag Index)
loadItemAjax(thumbnail.href, true);
@@ -14075,6 +14165,9 @@ window.cancelAnimFrame = (function () {
w.style.removeProperty('right');
});
swipeRT.isDraggingSidebar = false;
if (typeof window.redrawBgCanvas === 'function') {
window.redrawBgCanvas();
}
});
};
@@ -14332,6 +14425,9 @@ window.cancelAnimFrame = (function () {
w.style.removeProperty('padding-right');
w.style.removeProperty('right');
});
if (typeof window.redrawBgCanvas === 'function') {
window.redrawBgCanvas();
}
});
};
@@ -14503,6 +14599,14 @@ window.cancelAnimFrame = (function () {
onaraModal.style.setProperty('right', targetModalRight, 'important');
}
// Animate #bg canvas width in sync with sidebar so background stays centered
const bgCanvas = document.getElementById('bg');
if (bgCanvas && animateWrappers) {
const targetBgWidth = isHidden ? `calc(100vw - ${sidebarWidth}px)` : '100vw';
bgCanvas.style.setProperty('transition', 'width 0.3s ease-in-out', 'important');
bgCanvas.style.setProperty('width', targetBgWidth, 'important');
}
sidebar.style.setProperty('transition', 'transform 0.3s ease-in-out', 'important');
sidebar.style.transform = `translateX(${targetTranslate}px)`;
@@ -14515,6 +14619,7 @@ window.cancelAnimFrame = (function () {
sidebar.style.setProperty('transition', 'none', 'important');
edgeZone.style.setProperty('transition', 'none', 'important');
if (onaraModal) onaraModal.style.setProperty('transition', 'none', 'important');
if (bgCanvas) bgCanvas.style.setProperty('transition', 'none', 'important');
const toHidden = !isHidden;
document.body.classList.toggle('sidebar-right-hidden', toHidden);
localStorage.setItem('sidebarRightHidden', toHidden);
@@ -14527,11 +14632,18 @@ window.cancelAnimFrame = (function () {
onaraModal.style.removeProperty('transition');
onaraModal.style.removeProperty('right');
}
if (bgCanvas) {
bgCanvas.style.removeProperty('transition');
bgCanvas.style.removeProperty('width');
}
wrappers.forEach(w => {
w.style.removeProperty('transition');
w.style.removeProperty('padding-right');
w.style.removeProperty('right');
});
if (typeof window.redrawBgCanvas === 'function') {
window.redrawBgCanvas();
}
});
};