gpt4 book ai didi

javascript - 在滚动时固定/修复 Vanilla Javascript 中的多个元素时的性能 [第 2 部分]

转载 作者:行者123 更新时间:2023-11-29 23:22:29 25 4
gpt4 key购买 nike

在我之前的post我在没有框架的情况下在 Vanilla ES6 中滚动时寻求帮助修复某些部分。

简单的 HTML 结构:

<header class="forewords"><h1>Lorem some</h1>
</header>

<div class="wrapper">
<section class="project" id="item1">this is section 1</section>
<section class="project" id="item2">this is section 2</section>
<section class="project" id="item3">this is section 3</section>
</div>

<footer class="endings"><h1>Lorem something.</h1>
</footer>

这是完成工作的核心函数:

function pinElement() {

// Reset all styles
projects.forEach((project) => {
document.body.style.paddingTop = 0;
project.classList.remove('fixed');
});

// Get the index of the project that is closest to top
const valueClosestToScrollY = Math.max.apply(Math, projectsOffsetTop.filter((offsetTop) => offsetTop <= window.scrollY));
const idx = projectsOffsetTop.indexOf(valueClosestToScrollY);


// Otherwise, we set the appropriate styles and classes
if (window.scrollY >= projectsOffsetTop[idx]) {
document.body.style.paddingTop = `${projectsHeight[idx]}px`;
projects[idx].classList.add('fixed');
}

};

window.addEventListener('scroll', pinElement);

目前我遇到了两种逻辑问题,所以我选择另开一个话题。

首先,每次我第一次滚动时,我都会对所有内容调用 classList.remove('.fixed') 函数,然后突然调用 classList.add('.fixed') 在所选元素上。

这会在连续删除/添加类的所有滚动过程中产生“闪烁”效果(我猜对整体性能有负面影响)。

有办法解决吗?

第二个问题是我添加了一个事件监听器,以便在有人调整窗口大小时更新元素的偏移值和高度值。

function updateProjectsOffsetTop() {
projectsOffsetTop = projects.map(project => project.offsetTop);
projectsHeight = projects.map(project => project.offsetHeight);
};

window.addEventListener('resize', updateProjectsOffsetTop);

如果我在开始滚动之前调整窗口大小,这会很好地工作。但是,如果我在开始滚动后调整窗口大小,一切都会崩溃。

我想不出一种方法来实时更新值并将它们传递给滚动函数。如果可能的话,我想用 Vanilla ES6 解决这段代码,因为我正在尝试从该规范开始学习 Javascript。

我知道这可能是个简单的问题,但我是来学习的:)

在此先感谢并找到完整的 JS Fiddle。

const projects = Array.from(document.querySelectorAll('.project'));
let projectsOffsetTop = projects.map(project => project.offsetTop);
let projectsHeight = projects.map(project => project.offsetHeight);

function updateProjectsOffsetTop() {
projectsOffsetTop = projects.map(project => project.offsetTop);
projectsHeight = projects.map(project => project.offsetHeight);
};


function pinElement() {

// Reset all styles
projects.forEach((project) => {
document.body.style.paddingTop = 0;
project.classList.remove('fixed');
});

// Get the index of the project that is closest to top
const valueClosestToScrollY = Math.max.apply(Math, projectsOffsetTop.filter((offsetTop) => offsetTop <= window.scrollY));
const idx = projectsOffsetTop.indexOf(valueClosestToScrollY);


// Otherwise, we set the appropriate styles and classes
if (window.scrollY >= projectsOffsetTop[idx]) {
document.body.style.paddingTop = `${projectsHeight[idx]}px`;
projects[idx].classList.add('fixed');
}

};

window.addEventListener('resize', updateProjectsOffsetTop);
window.addEventListener('scroll', pinElement);
html {
box-sizing: border-box;
}

*, *::before, *::after {
box-sizing: inherit;
margin: 0;
padding: 0;
}

header, footer {
width: 100%;
padding: 10%;
background-color: grey;
position: relative;
}

.project {
width: 100%;
height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
top: 0;
}

#item1 {background-color: yellow;}
#item2 {background-color: blue;}
#item3 {background-color: red;}


.fixed {
position: fixed;
}
<header class="forewords"><h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum soluta ipsam quaerat cupiditate neque, necessitatibus amet nihil perferendis sunt minus! Exercitationem nulla inventore, aut beatae magnam, totam et minus hic.</h1>
</header>

<div class="wrapper">
<section class="project" id="item1">this is section 1</section>
<section class="project" id="item2">this is section 2</section>
<section class="project" id="item3">this is section 3</section>
</div>

<footer class="endings"><h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repudiandae vel, perferendis ullam totam recusandae sed repellendus cum! Molestiae, aut ut sequi eos quidem nam quo est, ad tempora inventore odit.</h1>
</footer>

最佳答案

您需要确保在删除和添加类之间没有间歇性渲染。这些重绘导致它在不同的点重新渲染,使其闪烁。尝试将固定类的删除和设置嵌套在对 request animation frame 的调用中.事实上,您的固定功能足够小,您可以像这样在对它的调用中将其全部设置:

function pinElement() {
window.requestAnimationFrame(() => {
// Reset all styles
projects.forEach((project) => {
document.body.style.paddingTop = 0;
project.classList.remove('fixed');
});

// Get the index of the project that is closest to top
const valueClosestToScrollY = Math.max.apply(Math, projectsOffsetTop.filter((offsetTop) => offsetTop <= window.scrollY));
const idx = projectsOffsetTop.indexOf(valueClosestToScrollY);


// Otherwise, we set the appropriate styles and classes
if (window.scrollY >= projectsOffsetTop[idx]) {
document.body.style.paddingTop = `${projectsHeight[idx]}px`;
projects[idx].classList.add('fixed');
}
});

};

window.addEventListener('scroll', pinElement);

在此答案中更新了您的代码片段以测试您的评论,似乎对我来说工作正常:编辑:刚刚注意到我上面的示例缺少闭包。固定

const projects = Array.from(document.querySelectorAll('.project'));
let projectsOffsetTop = projects.map(project => project.offsetTop);
let projectsHeight = projects.map(project => project.offsetHeight);

function updateProjectsOffsetTop() {
projectsOffsetTop = projects.map(project => project.offsetTop);
projectsHeight = projects.map(project => project.offsetHeight);
};


function pinElement() {
window.requestAnimationFrame(() =>{
// Reset all styles
projects.forEach((project) => {
document.body.style.paddingTop = 0;
project.classList.remove('fixed');
});

// Get the index of the project that is closest to top
const valueClosestToScrollY = Math.max.apply(Math, projectsOffsetTop.filter((offsetTop) => offsetTop <= window.scrollY));
const idx = projectsOffsetTop.indexOf(valueClosestToScrollY);


// Otherwise, we set the appropriate styles and classes
if (window.scrollY >= projectsOffsetTop[idx]) {
document.body.style.paddingTop = `${projectsHeight[idx]}px`;
projects[idx].classList.add('fixed');
}
})

};

window.addEventListener('resize', updateProjectsOffsetTop);
window.addEventListener('scroll', pinElement);
html {
box-sizing: border-box;
}

*, *::before, *::after {
box-sizing: inherit;
margin: 0;
padding: 0;
}

header, footer {
width: 100%;
padding: 10%;
background-color: grey;
position: relative;
}

.project {
width: 100%;
height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
top: 0;
}

#item1 {background-color: yellow;}
#item2 {background-color: blue;}
#item3 {background-color: red;}


.fixed {
position: fixed;
}
<header class="forewords"><h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum soluta ipsam quaerat cupiditate neque, necessitatibus amet nihil perferendis sunt minus! Exercitationem nulla inventore, aut beatae magnam, totam et minus hic.</h1>
</header>

<div class="wrapper">
<section class="project" id="item1">this is section 1</section>
<section class="project" id="item2">this is section 2</section>
<section class="project" id="item3">this is section 3</section>
</div>

<footer class="endings"><h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repudiandae vel, perferendis ullam totam recusandae sed repellendus cum! Molestiae, aut ut sequi eos quidem nam quo est, ad tempora inventore odit.</h1>
</footer>

关于javascript - 在滚动时固定/修复 Vanilla Javascript 中的多个元素时的性能 [第 2 部分],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50177843/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com