Reputation:
I am looking to add 'opacity' class to list items as the top of a div becomes visible in the viewport and remove the class once the div leaves the viewport and vice versa when scrolling up
Here is pen https://codepen.io/anon/pen/pYOrOV
I am not very familiar with jquery so might be making silly mistakes here but, Is it using the waypoint function the way to go or something more like the second option? any suggestions would be much appreciated thank you.
$('.wrapperright').scroll(function () {
if(y >= s_body.top && y < e_body.top){
$('#generationanxiety').addClass('opacity');
}
else
{
$('#generationanxiety').removeClass('opacity');
}
});
Upvotes: 2
Views: 3169
Reputation: 5205
Checking if an item is in the viewport is easiest with getBoundingClientRect()
. So I've used that in combination with data
attributes on the div
around the images - in order to match them with the id
of the corresponding li
item.
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>
The same relationship between id
of the list item and matching data
attribute I've also used to store the scrolling positions of the images ahead of clicking, in order to fix the anchor scrolling part.
After some feedback an extra bit of code was added to make sure only one list item gets highlighted at a time, depending on which image is "emerging" (by checking the scroll direction).
I've somewhat changed the HTML also because div
isn't a valid child of ul
and the wrapper element seems otherwise unnecessary here anyway. Lastly a minor CSS fix to correct the overflow of the element on the right and a few band aids to fix horizontal overflow issues (vw
isn't very universally compatible with desktop browsers). The style is a bit out of the scope of the question otherwise, I've altered it only minimally.
Upvotes: 1
Reputation: 495
Maybe this...
var topofDiv = $("#generationanxiety").offset().top; //gets offset div
var height = $("#generationanxiety").outerHeight(); //gets height of div
$(window).scroll(function(){
if($(window).scrollTop() > (topofDiv + height)){
console.log('This is where the div bottom leaves the window.')
$('#generationanxiety').removeClass('opacity');
}
else{
$('#generationanxiety').addClass('opacity');
}
});
and for smoothness add this additional CSS Code:
#WrapperDiv{
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
to the parent div
Upvotes: 0