Skip to content

Instantly share code, notes, and snippets.

@julrich
Created February 10, 2022 15:44
Show Gist options
  • Save julrich/d4e4150f7b9562af4a1f37f479ed22b6 to your computer and use it in GitHub Desktop.
Save julrich/d4e4150f7b9562af4a1f37f479ed22b6 to your computer and use it in GitHub Desktop.
import "@kickstartds/core/lib/container-queries";
import { Component, define } from "@kickstartds/core/lib/core";
import { windowEvents } from "@kickstartds/core/lib/utils";
const desktopImageOffsetAngle = 60;
const mobileImageOffsetAngle = 75;
const mobileOffsetRotateAngle = 45;
const backgroundRotateFactor = -0.25;
const maxBlur = 4;
const identifier = "enc.wheel";
const rad = Math.PI / 180;
class Wheel extends Component {
static identifier = identifier;
constructor(element) {
super(element);
const scrollRoot =
element.closest('[data-testid="document-panel-scroller"]') || document; // sanity fix
const wheel = element.querySelector(".text-media__gallery");
const images = wheel.querySelectorAll(".text-media__media");
let magicFactor;
let wheelRadius;
let isSmallScreen;
let imageOffsetAngle;
function getScrollPosition() {
const coords = element.getBoundingClientRect();
const height = coords.height - window.innerHeight;
return Math.min(1, Math.max(0, (-1 * coords.top) / height));
}
function update() {
requestAnimationFrame(() => {
const scroll = getScrollPosition();
const rotate = -360 * scroll * magicFactor;
wheel.style.setProperty(
"--c-wheel--rotate",
`${rotate * backgroundRotateFactor}deg`
);
images.forEach((image, index) => {
const angle =
rotate +
imageOffsetAngle * index +
(isSmallScreen ? mobileOffsetRotateAngle : 0);
const radians = angle * rad;
const x = Math.cos(radians) * wheelRadius;
const y = Math.sin(radians) * wheelRadius;
const scale = Math.max(
0,
1 -
Math.abs(angle - (isSmallScreen ? mobileOffsetRotateAngle : 0)) /
180
);
image.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;
image.style.filter = `blur(${(1 - scale) * maxBlur}px)`;
// image.style.zIndex = Math.floor(scale * images.length);
});
});
}
function init() {
isSmallScreen = element.offsetWidth < 640;
wheelRadius = isSmallScreen
? wheel.clientWidth / 1.5
: wheel.clientWidth / 1.2;
imageOffsetAngle = isSmallScreen
? mobileImageOffsetAngle
: desktopImageOffsetAngle;
magicFactor = ((images.length - 1) * imageOffsetAngle) / 360;
update();
}
let isActive = false;
const observer = new IntersectionObserver((entries) => {
let inViewport = false;
for (const entry of entries) {
inViewport = entry.isIntersecting;
}
if (inViewport && !isActive) {
init();
scrollRoot.addEventListener("scroll", update, {
passive: true,
});
} else if (!inViewport && isActive) {
scrollRoot.removeEventListener("scroll", update);
}
isActive = inViewport;
});
observer.observe(element);
window.rm.radio.on(windowEvents.resize, init);
}
}
define(identifier, Wheel);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment