Adjust perspective origin if viewport is near vertical edges

If the origin is set to the center of the screen for a small 3d element
that's near the top or bottom, then it looks out of place and can't be
scrolled to fit nicely in view.  Adjust the origin to stay inside the
bounds of the viewport when scrolled to the edge of the screen in this
case.
This commit is contained in:
Hornwitser 2024-11-12 00:32:53 +01:00
parent e62b947c42
commit 78d3f56672

View file

@ -2,12 +2,28 @@ function setViewportOffset(viewport) {
// Calculate the distance from the top of the element to the center of the screen. // 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. // This is an accurate rendering, but we might want to change it for artistic effects.
const windowHeight = window.innerHeight; const windowHeight = window.innerHeight;
const rect = viewport.getBoundingClientRect(); const viewportRect = viewport.getBoundingClientRect();
if (rect.top > windowHeight || rect.bottom < 0) { if (viewportRect.top > windowHeight || viewportRect.bottom < 0) {
return; return;
} }
const yOffset = windowHeight / 2 - rect.top; const documentRect = document.documentElement.getBoundingClientRect();
viewport.style.setProperty('--y-offset', yOffset+"px"); /*
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"); const viewports = document.querySelectorAll(".viewport");