英文:
javascript - Scale and translate image from center of window to fixed position
问题
我是新手JavaScript,正在创建一个技术演示网站来自学。我首先尝试制作一个闪屏和导航栏,但一直在努力使闪屏图像适当地转换到导航栏。
图像始于客户端窗口的中央,并且应平滑缩放和平移,使用用户的scrollY位置移动到窗口的左上角。一旦变换动画完成,图标应始终与屏幕边缘的顶部和左侧保持固定数量的像素,而不考虑窗口尺寸(变换函数应适应此情况)。
我已尝试多种方法来根据窗口的宽度和高度动态平移图像,但这是我能够做到的最接近的方式: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";
}
});
图像始于屏幕中央并平滑缩放,但在尝试不同窗口尺寸时效果不如预期。
我搜索了这个问题的答案,但找不到符合特定要求的答案,ChatGPT 也没有提供特别有帮助的信息。感激任何帮助!
祝好,
亚当
英文:
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
答案1
得分: 0
已经弄清楚了!问题出在从CSS中的.icon
类中移除了transform-origin: top left
标签,并稍微调整了平移值:
const icon = document.querySelector(".icon");
// 在页面加载时动态设置位置
window.addEventListener("load", () => {
icon.style.left = window.innerWidth / 2 - icon.width / 2 + "px";
icon.style.top = window.innerHeight / 2 - icon.height / 2 + "px";
});
// 在中心和左上角之间缩放和平移图标
window.addEventListener("scroll", () => {
// 可以根据具体需求调整的巧妙数学运算
let scale = 100 - window.scrollY / 6;
// (window.innerWidth - icon.width) / 2 是初始位置(中心)
// (window.scrollY * window.innerWidth) / 1000 平移到左上角
// (window.scrollY / 100) * 10 确定边缘和图标之间的'padding'
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) {
// 从中心变换到固定的左上角位置
icon.style.transform = "scale(" + scale + "%)";
icon.style.left = left + "px";
icon.style.top = top + "px";
} else {
// 修复由于scrollY跳跃引起的变换不精确性
// 下面的值与上面计算的值相同,
// 但使用500替代window.scrollY进行解决和简化
icon.style.top = 50 - icon.height / 2 + 'px';
icon.style.left = 50 - icon.width / 2 + 'px';
icon.style.transform = 'scale(17%)';
}
});
如果需要交互式演示,同样的代码已经更新到这个CodePen中:https://codepen.io/Audity/pen/KKryrjV
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论