I am new to javascript and making a tech demo site to teach it to myself. I started by trying to make a splash screen and navbar but have been struggling to have the splash screen image transform appropriately to the navbar.
The image starts in the center of the client window, and should scale and translate smoothly using the user's scrollY position to the top left of the window. Once the transform animation finishes, the icon should always be a fixed number of pixels from the top and left of the edge of the screen, regardless of the window dimensions (the transform function should adapt to this).
I have tried as many ways to dynamically translate the image according to the width and height of the window, but this was as close as I could get: https://codepen.io/Audity/pen/KKryrjV
const icon = document.querySelector(".icon");
// Set position dynamically on page load
window.addEventListener("load", () => {
icon.style.left = window.innerWidth / 2 - icon.width / 2 + "px";
icon.style.top = window.innerHeight / 2 - icon.height / 2 + "px";
});
// Scale and translate icon between center and top left
window.addEventListener("scroll", () => {
let scale = 100 - window.scrollY / 5.75;
let left = (window.innerWidth - icon.width) / 2 - (window.scrollY * window.innerWidth) / 2000;
let top = (window.innerHeight - icon.height) / 2 - (window.scrollY * window.innerHeight) / 2000;
if (window.scrollY <= 500) {
console.log("transform: \nscale: " + scale + "%\nleft: " + left + "px\ntop: " + top + "px");
// Scale and translate icon
icon.style.transform = "scale(" + scale + "%)";
icon.style.left = left + "px";
icon.style.top = top + "px";
}
});
The image starts in the center of the screen and scales smoothly, but misses the mark when tried with different window dimensions.
I searched for answers to this issue but couldn't find any which had these same particular requirements, and ChatGPT was not particularly helpful either. Would appreciate any help!
Cheers, Adam
Figured it out! Came down to removing the transform-origin: top left
tag from the .icon
class in css, and playing with the translation values a bit:
const icon = document.querySelector(".icon");
// Set position dynamically on page load
window.addEventListener("load", () => {
icon.style.left = window.innerWidth / 2 - icon.width / 2 + "px";
icon.style.top = window.innerHeight / 2 - icon.height / 2 + "px";
});
// Scale and translate icon between center and top left
window.addEventListener("scroll", () => {
// Hacky math that can be adjusted to fit specific needs
let scale = 100 - window.scrollY / 6;
// (window.innerWidth - icon.width) / 2 is the initial position (center)
// (window.scrollY * window.innerWidth) / 1000 translates to the top left corner
// (window.scrollY / 100) * 10 determines the 'padding' between the edges and the icon
let left =
(window.innerWidth - icon.width) / 2 -
(window.scrollY * window.innerWidth) / 1000 +
(window.scrollY / 100) * 10;
let top =
(window.innerHeight - icon.height) / 2 -
(window.scrollY * window.innerHeight) / 1000 +
(window.scrollY / 100) * 10;
if (window.scrollY <= 500) {
// Transform from center to fixed top left position
icon.style.transform = "scale(" + scale + "%)";
icon.style.left = left + "px";
icon.style.top = top + "px";
} else {
// Fix transform inaccuracies caused by scrollY jumps
// The values below are the same as the calculated values above,
// but solved and simplified with 500 in place of window.scrollY
icon.style.top = 50 - icon.height / 2 + 'px';
icon.style.left = 50 - icon.width / 2 + 'px';
icon.style.transform = 'scale(17%)';
}
});
The same codepen has also been updated with this solution in case an interactive demo is desired: https://codepen.io/Audity/pen/KKryrjV