diff --git a/web/viewport.js b/web/viewport.js index 29030d5..5bf20e5 100644 --- a/web/viewport.js +++ b/web/viewport.js @@ -2,12 +2,28 @@ function setViewportOffset(viewport) { // Calculate the distance from the top of the element to the center of the screen. // This is an accurate rendering, but we might want to change it for artistic effects. const windowHeight = window.innerHeight; - const rect = viewport.getBoundingClientRect(); - if (rect.top > windowHeight || rect.bottom < 0) { + const viewportRect = viewport.getBoundingClientRect(); + if (viewportRect.top > windowHeight || viewportRect.bottom < 0) { return; } - const yOffset = windowHeight / 2 - rect.top; - viewport.style.setProperty('--y-offset', yOffset+"px"); + const documentRect = document.documentElement.getBoundingClientRect(); + /* + If the the bounds of a viewport element is close to the top or bottom + of the page the perspective origin is adjusted so that it is still + contained inside of the bounds of the element to not look out of place. + This controls how much into the bounds the perspective origin should be + pushed when the screen in scrolled all the way to the top/bottom. + */ + const endOffset = viewportRect.height * 0.25; + const origin = Math.min( + (viewportRect.bottom - documentRect.top) - endOffset, + Math.max( + windowHeight / 2, + windowHeight - (documentRect.bottom - viewportRect.top) + endOffset, + ) + ); + const yOffset = origin - viewportRect.top; + viewport.style.setProperty('--y-offset', yOffset + "px"); } const viewports = document.querySelectorAll(".viewport");