使用getBoundingClientRect() 最容易检查项目是否在视口中。因此,我将其与图像周围 div 上的 data 属性结合使用 - 以便将它们与相应 li 项目的 id 匹配。
Demo with explanatory comments
$(window).on('load', function() {
var pouch = $('.wrapperright'),
items = pouch.find('div'),
gate, spot = {},
zone = pouch.scrollTop(),
haze = 'opacity';
$(this).resize(collectInfo).resize();
pouch.scroll(function() {
items.each(function() {
var aim = $('#' + $(this).data('target')),
edges = this.getBoundingClientRect(),
apex = Math.round(edges.top),
nadir = Math.round(edges.bottom);
if (apex < gate && nadir > 0) aim.removeClass(haze);
else aim.addClass(haze);
});
var rise = $('.bio li').not('.' + haze),
turf = pouch.scrollTop();
if (rise.length > 1) {
if (turf > zone) rise.eq(0).addClass(haze);
else rise.eq(1).addClass(haze);
}
zone = turf;
});
$('.bio li').click(function() {
if (zone == spot[this.id]) return;
pouch.stop().animate({scrollTop: spot[this.id]}, 1500);
});
function collectInfo() {
gate = $(this).height();
items.each(function() {
spot[$(this).data('target')] = Math.round($(this).position().top+zone);
});
}
});
$(window).on('load', function() {
var pouch = $('.wrapperright'),
items = pouch.find('div'),
gate, spot = {},
zone = pouch.scrollTop(),
haze = 'opacity';
$(this).resize(collectInfo).resize();
pouch.scroll(function() {
items.each(function() {
var aim = $('#' + $(this).data('target')),
edges = this.getBoundingClientRect(),
apex = Math.round(edges.top),
nadir = Math.round(edges.bottom);
if (apex < gate && nadir > 0) aim.removeClass(haze);
else aim.addClass(haze);
});
var rise = $('.bio li').not('.' + haze),
turf = pouch.scrollTop();
if (rise.length > 1) {
if (turf > zone) rise.eq(0).addClass(haze);
else rise.eq(1).addClass(haze);
}
zone = turf;
});
$('.bio li').click(function() {
if (zone == spot[this.id]) return;
pouch.stop().animate({scrollTop: spot[this.id]}, 1500);
});
function collectInfo() {
gate = $(this).height();
items.each(function() {
spot[$(this).data('target')] = Math.round($(this).position().top+zone);
});
}
});
html, body {
margin: 0;
overflow-x: hidden;
overflow-y: hidden;
}
.wrapper {
display: grid;
grid-template-columns: repeat(2, 1fr);
height: 100vh;
margin: 0;
grid-gap: 0;
}
.wrapperleft {
grid-column-start: 1;
grid-column-end: 1;
grid-template-rows: auto;
width: 50vw;
max-height: 100%;
overflow: hidden;
margin: 0;
}
.bio {
margin: 20px;
}
.bio ul {
margin-top: 20px;
padding: 0;
}
.bio h1 {
font-family: sans-serif;
font-weight: 400;
font-size: 3.2em;
list-style: none;
margin: 0;
border-bottom: 2px solid #000;
display: inline;
}
.bio ul li {
font-family: sans-serif;
font-weight: 400;
font-size: 3.2em;
list-style: none;
padding-bottom: 10px;
cursor: pointer;
-webkit-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.back {
position: absolute;
bottom: 0;
margin-left: 20px;
}
.back h1 {
font-family: sans-serif;
font-weight: 400;
font-size: 1.5em;
}
.wrapperright {
grid-column-start: 2;
grid-column-end: 2;
grid-template-rows: 200px;
border-left: 2px solid #000;
width: 50vw;
overflow-x: hidden;
overflow-y: auto;
}
.wrapperright img {
width: 50vw;
max-height: 100%;
display: block;
}
.opacity {
opacity: 0.4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="wrapperleft">
<div class="bio">
<ul>
<li id="generation" class="opacity">01 Generation Anxiety</li>
<li id="lekhena" class="opacity">02 Lekhenaporter.com</li>
<li id="bodys" class="opacity">03 Body(s) Under Negotiation</li>
<li id="glitter" class="opacity">04 Glitter Boy Cosmetics</li>
<li id="juice" class="opacity">05 Juice WRLD Cover Art</li>
</ul>
</div>
<div class="back">
<h1>← Back</h1>
</div>
</div>
<div class="wrapperright">
<img src="http://media-s3-us-east-1.ceros.com/vevo/images/2017/11/07/8d018e81643b41c3561b5ab4f5bf504b/iamddb-contact-sheet1.jpg" alt="image1">
<div data-target="generation">
<img src="https://dazedimg-dazedgroup.netdna-ssl.com/786/azure/dazed-prod/1180/0/1180791.jpg" alt="image2">
</div>
<div data-target="lekhena">
<img src="http://kendrickbrinson.com/wp-content/uploads/2014/03/YoungThug_Portraits-029.jpg" alt="image3">
</div>
<div data-target="bodys">
<img src="https://www.thunderstudios.com/wp-content/uploads/2016/03/Calvin-15.jpg" alt="image4">
</div>
<div data-target="glitter">
<img src="https://4c79id2ej5i11apui01ll2wc-wpengine.netdna-ssl.com/wp-content/uploads/2018/01/IAMDDB-Gallery-3.jpg" alt="image5">
</div>
<div data-target="juice">
<img src="https://www.thunderstudios.com/wp-content/uploads/2016/03/Calvin-15.jpg" alt="image6">
</div>
</div>
</div>
列表项的id与匹配data属性的关系相同,我也用过存储点击前图片的滚动位置,以修复锚点滚动部分。
在一些反馈之后,添加了额外的代码以确保一次仅突出显示一个列表项,具体取决于哪个图像“出现”(通过检查滚动方向)。
我也对 HTML 进行了一些更改,因为 div 不是 ul 的有效子代,而且包装元素在此处似乎是不必要的。最后,一个小的 CSS 修复来纠正右侧元素的溢出和一些修复水平溢出问题的创可贴(vw 与桌面浏览器的兼容性不是很普遍)。样式有点超出问题的范围,否则我只做了很小的改动。