在我以前的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')
。
这导致&#34;闪烁&#34;在所有滚动中的效果,其中类被删除/添加连续(对我的整体性能有负面影响)。
有没有办法解决这个问题?
第二个问题是,当有人调整窗口大小时,我添加了一个事件监听器来更新元素的偏移量和高度值。
function updateProjectsOffsetTop() {
projectsOffsetTop = projects.map(project => project.offsetTop);
projectsHeight = projects.map(project => project.offsetHeight);
};
window.addEventListener('resize', updateProjectsOffsetTop);
如果我在开始滚动之前调整窗口大小,这可以正常工作。但是,如果我在启动滚动后调整窗口大小,一切都会破坏。
我无法找到更新实时值并将其传递给滚动功能的方法。我想用Vanilla ES6解决这个代码,如果可能的话,因为我试图从该规范开始学习Javascript。
我知道也许这是一个简单的问题,但我在这里学习:)
提前致谢并找到完整的JS小提琴。
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);
&#13;
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;
}
&#13;
<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>
&#13;
答案 0 :(得分:1)
您需要确保在删除和添加课程之间不会出现间歇性渲染。那些重绘会导致它在不同点重新渲染,使其闪烁。尝试在对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);
&#13;
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;
}
&#13;
<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>
&#13;