我正在尝试使用CSS和JavaScript实现滑动滚动视差效果,这种效果被称为“slip-scroll parallax”。当屏幕向下滚动时,右上角的徽标将更改其背景颜色以与下方形成对比。左侧还有一个导航按钮也会做同样的事情。
目前我已经实现了以下内容...
目前我已经实现了以下内容...
// Detect request animation frame
var scroll = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
// IE Fallback, you can even fallback to onscroll
||
function(callback) {
window.setTimeout(callback, 1000 / 60)
};
var lastPosition = -1;
// my Variables
var lastSection = false;
var replaceItemTop = -1;
var replaceItemBottom = -1;
var replaceItemHeight = -1;
// The Scroll Function
function loop() {
var top = window.pageYOffset;
// my variables
// my sections to calculate stuff
var sections = document.querySelectorAll('.section');
var replaceContainer = document.querySelectorAll('.js-replace');
var replaceItem = document.querySelectorAll('.js-replace__item');
if (replaceItem.length > 0) {
// get top position of item from container, because image might not have loaded
replaceItemTop = parseInt(replaceContainer[0].getBoundingClientRect().top);
replaceItemHeight = replaceItem[0].offsetHeight;
replaceItemBottom = replaceItemTop + replaceItemHeight;
}
var sectionTop = -1;
var sectionBottom = -1;
var currentSection = -1;
// Fire when needed
if (lastPosition == window.pageYOffset) {
scroll(loop);
return false;
} else {
lastPosition = window.pageYOffset;
// Your Function
Array.prototype.forEach.call(sections, function(el, i) {
sectionTop = parseInt(el.getBoundingClientRect().top);
sectionBottom = parseInt(el.getBoundingClientRect().bottom);
// active section
if ((sectionTop <= replaceItemBottom) && (sectionBottom > replaceItemTop)) {
// check if current section has bg
currentSection = el.classList.contains('section--bg');
// switch class depending on background image
if (currentSection) {
replaceContainer[0].classList.remove('js-replace--reverse');
} else {
replaceContainer[0].classList.add('js-replace--reverse')
}
}
// end active section
// if active Section hits replace area
if ((replaceItemTop < sectionTop) && (sectionTop <= replaceItemBottom)) {
// animate only, if section background changed
if (currentSection != lastSection) {
document.documentElement.style.setProperty('--replace-offset', 100 / replaceItemHeight * parseInt(sectionTop - replaceItemTop) + '%');
}
}
// end active section in replace area
// if section above replace area
if (replaceItemTop >= sectionTop) {
// set offset to 0 if you scroll too fast
document.documentElement.style.setProperty('--replace-offset', 0 + '%');
// set last section to current section
lastSection = currentSection;
}
});
}
// Recall the loop
scroll(loop)
}
// Call the loop for the first time
loop();
window.onresize = function(event) {
loop();
};
/* variables */
:root {
/* this value is going to be changed by javascript */
--replace-offset: 50%;
--replace-offset-2: calc((100% - var(--replace-offset)) * -1)
}
a {
text-decoration: none;
}
/* set image position */
img {
vertical-align: bottom;
}
.footer {
background-color: black;
color: white;
padding-top: 50px;
padding-bottom: 50px;
text-align: center;
}
/* without fixed header this makes no sense */
.header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
}
.header_nav {
position: fixed;
top: 50%;
transform: translateY(-50%);
left: 0;
z-index: 9;
}
.logo {
background-color: white;
display: inline-block;
border: solid;
padding: 10px;
border-radius: 10px;
font-size: 2em;
}
.logo a {
color: black;
}
.logo--invert {
background-color: black;
color: white;
border-color: white;
}
.logo--invert a {
color: white;
}
.sidelogo {
background-color: white;
display: inline-block;
border: solid;
padding: 10px;
border-radius: 10px;
font-size: 2em;
}
.sidelogo a {
color: black;
}
.sidelogo--invert {
background-color: black;
color: white;
border-color: white;
}
.sidelogo--invert a {
color: white;
}
.section {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
section--1 {
height: 100vh;
width: 100%;
}
.hero {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://www.w3schools.com/howto/photographer.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.section--2 {
background: white;
}
.section--3 {
background: black;
color: white;
}
/**
This is the interesting part
**/
/* align content above each other without absolute */
.js-replace {
display: grid;
}
.js-replace__item {
grid-row: -1 / 1;
grid-column: -1 / 1;
overflow: hidden;
will-change: transform;
}
/* item to replace with */
.js-replace__item {
transform: translateY(calc(var(--replace-offset) * 1));
}
.js-replace__content {
/* fixes problem with calculating correct height in js */
border: 1px solid transparent;
will-change: transform;
transform: translateY(calc(var(--replace-offset) * -1));
}
/* previous replace item*/
.js-replace__item--active {
transform: translateY(calc(var(--replace-offset-2) * 1));
}
.js-replace__item--active .js-replace__content {
transform: translateY(calc(var(--replace-offset-2) * -1));
}
/* REVERSE ANIMATION */
.js-replace--reverse .js-replace__item {
transform: translateY(calc(var(--replace-offset-2) * 1));
}
.js-replace--reverse .js-replace__content {
transform: translateY(calc(var(--replace-offset-2) * -1));
}
/* previous replace item*/
.js-replace--reverse .js-replace__item--active {
transform: translateY(calc(var(--replace-offset) * 1));
}
.js-replace--reverse .js-replace__item--active .js-replace__content {
transform: translateY(calc(var(--replace-offset) * -1));
}
<body class="body">
<div class="header">
<!-- replace content -->
<div class="header__logo js-replace">
<!-- item to replace -->
<div class="js-replace__item js-replace__item--active">
<div class="js-replace__content">
<div class="logo"><a href="#">Logo</a></div>
</div>
</div>
<!-- end item to replace -->
<!-- item to replace with -->
<div class="js-replace__item">
<div class="js-replace__content">
<div class="logo logo--invert"><a href="#">Logo</a></div>
</div>
</div>
<!-- end item to replace with -->
</div>
<!-- end replace content -->
</div>
<div class="header_nav">
<!-- replace content -->
<div class="header__side js-replace">
<!-- item to replace -->
<div class="js-replace__item js-replace__item--active">
<div class="js-replace__content">
<div class="sidelogo"><a href="#">Nav</a></div>
</div>
</div>
<!-- end item to replace -->
<!-- item to replace with -->
<div class="js-replace__item">
<div class="js-replace__content">
<div class="sidelogo sidelogo--invert"><a href="#">Nav</a></div>
</div>
</div>
<!-- end item to replace with -->
</div>
<!-- end replace content -->
</div>
<main class="main">
<section class="section--1 section">
<div class="hero">
</div>
</section>
<section class="section--2 section section--bg">
<h1>Section 2</h1>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis
tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan
porttitor, facilisis luctus, metus</p>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo.</p>
</section>
<section class="section--3 section">
<h1>Section 3</h1>
<p>
<strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
sagittis tempus lacus enim ac dui. <a href="#">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.
</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus
turpis elit sit amet quam. Vivamus pretium ornare est.</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
</section>
<section class="section--4 section section--bg">
<h1>Section 4</h1>
<p>
Some great section 4 content
</p>
<ul>
<li>This is a list item</li>
<li>This is a list item</li>
<li>This is a list item</li>
<li>This is a list item</li>
<li>This is a list item</li>
</ul>
</section>
<section class="section--5 section section--bg">
<h1 class="section__title">
Section 5
</h1>
<p>
This is some random content for section 5
</p>
</section>
</main>
<footer class="footer section">
<form action="#" method="post">
<div>
<label for="name">Text Input:</label>
<input type="text" name="name" id="name" value="" tabindex="1" />
</div>
<div>
<h4>Radio Button Choice</h4>
<label for="radio-choice-1">Choice 1</label>
<input type="radio" name="radio-choice-1" id="radio-choice-1" tabindex="2" value="choice-1" />
<label for="radio-choice-2">Choice 2</label>
<input type="radio" name="radio-choice-2" id="radio-choice-2" tabindex="3" value="choice-2" />
</div>
<div>
<label for="select-choice">Select Dropdown Choice:</label>
<select name="select-choice" id="select-choice">
<option value="Choice 1">Choice 1</option>
<option value="Choice 2">Choice 2</option>
<option value="Choice 3">Choice 3</option>
</select>
</div>
<div>
<label for="textarea">Textarea:</label>
<textarea cols="40" rows="8" name="textarea" id="textarea"></textarea>
</div>
<div>
<label for="checkbox">Checkbox:</label>
<input type="checkbox" name="checkbox" id="checkbox" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
</footer>
</body>
右侧的Logo表现正常,当您向下滚动页面时,背景会发生变化。
然而,左侧的导航栏没有正确工作,我认为它需要添加一些偏移量,因为当前它会随着导航栏的更改而更改。
有任何想法是我在哪里出错了吗?