rotation edge case
This commit is contained in:
@@ -749,15 +749,58 @@ App.videos = App.videos || {};
|
||||
update();
|
||||
};
|
||||
|
||||
// Records the topmost card crossing (or just below) the viewport top,
|
||||
// plus how far its top sits from the viewport top. A column re-pack (on
|
||||
// resize / orientation change) reassigns every card's position, so the
|
||||
// raw scrollTop would otherwise point at a different video afterwards.
|
||||
// Anchoring on the topmost visible card (rather than the centred one)
|
||||
// is independent of the viewport height, which has *already* changed by
|
||||
// the time a resize/orientation event fires -- so it stays correct even
|
||||
// as portrait<->landscape swaps the height out from under us.
|
||||
const captureAnchor = function() {
|
||||
let anchor = null;
|
||||
let bestTop = Infinity;
|
||||
mounted.forEach((card, i) => {
|
||||
const rect = card.getBoundingClientRect();
|
||||
if (rect.bottom <= 0) return; // fully scrolled past
|
||||
if (rect.top < bestTop) {
|
||||
bestTop = rect.top;
|
||||
anchor = { index: i, offsetTop: rect.top };
|
||||
}
|
||||
});
|
||||
return anchor;
|
||||
};
|
||||
|
||||
// Scrolls so the anchored card sits at the same viewport offset it had
|
||||
// before the re-pack, keeping the user's place across the layout change.
|
||||
const restoreAnchor = function(anchor) {
|
||||
if (!anchor) return;
|
||||
const el = grid();
|
||||
const l = layout[anchor.index];
|
||||
if (!el || !l) return;
|
||||
const gridTopDoc = el.getBoundingClientRect().top + window.scrollY;
|
||||
const target = gridTopDoc + l.top - anchor.offsetTop;
|
||||
window.scrollTo(0, Math.max(0, target));
|
||||
};
|
||||
|
||||
let resizeRaf = null;
|
||||
let pendingAnchor = null;
|
||||
const ensureInit = function() {
|
||||
if (!cols) measureMetrics();
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
window.addEventListener('scroll', scheduleUpdate, { passive: true });
|
||||
window.addEventListener('resize', () => {
|
||||
// Capture before the re-pack (positions are still the old ones)
|
||||
// and keep the earliest anchor across a burst of resize events.
|
||||
if (!pendingAnchor) pendingAnchor = captureAnchor();
|
||||
if (resizeRaf) cancelAnimationFrame(resizeRaf);
|
||||
resizeRaf = requestAnimationFrame(relayout);
|
||||
resizeRaf = requestAnimationFrame(() => {
|
||||
resizeRaf = null;
|
||||
relayout();
|
||||
restoreAnchor(pendingAnchor);
|
||||
pendingAnchor = null;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user