J'essaie de changer la couleur de <li>
éléments lorsqu'ils représentent entre 30% et 60% de la fenêtre d'affichage.
J'ai donc cette grille d'éléments empilés côte à côte comme ceci:
J'ai rencontré quelques plugins comme Waypoints, Viewport Checker et quelques autres mais rien de bon.
Une idée?
J'utilise une structure assez simple:
[~ # ~] html [~ # ~]
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/styles.css">
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script src="js/main.js"></script>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
</html>
CSS:
ul {
margin: auto;
}
ul li {
width: 300px;
height: 200px;
background: #f5f5f5;
float: left;
margin: 10px;
}
ul li.middleviewport{
background:red;
}
Amélioration de la solution de @ Tushar pour la faire fonctionner même après un redimensionnement de la fenêtre (un recalcul de la fenêtre est nécessaire à chaque fois, pas seulement au début), et pour la faire démarrer déjà en surbrillance, sans avoir besoin de faire défiler.
Également amélioré un peu le graphique de l'exemple pour mettre en évidence la zone intéressée.
$(document).ready(function() {
$(window).on('scroll', function() {
var windowHeight = $(window).height(),
gridTop = windowHeight * .3,
gridBottom = windowHeight * .6;
$('ul li').each(function() {
var thisTop = $(this).offset().top - $(window).scrollTop();
if (thisTop > gridTop && (thisTop + $(this).height()) < gridBottom) {
$(this).css('background', 'red');
} else {
$(this).css('background', 'silver');
}
});
});
$(window).trigger('scroll');
});
ul {
margin: auto;
}
ul li {
width: 300px;
height: 10px;
background: silver;
float: left;
margin: 10px;
list-style: none;
}
ul li.middleviewport {
background: red;
}
#viewportMask {
position: fixed;
top: 30%;
bottom: 40%;
left: 0;
right: 0;
background: red;
opacity: 0.2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="viewportMask"></div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
[[Cet exemple vérifie si TOUT élément de l'élément se trouve dans la région spécifiée]]
Lorsque vous avez les coordonnées supérieure et inférieure de deux cases, vous pouvez vérifier si les deux cases se chevauchent en vérifiant:
box1.top < box2.bottom && box1.bottom > box2.top
Dans l'exemple suivant, box1 est la partie 30% -60% de la fenêtre tandis que box2 est chaque élément de liste. Ajoutez la fonction anti-rebond et nous avons:
var timeout;
$(window).on("load scroll resize", function() {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function() {
var $window = $(window),
hitbox_top = $window.scrollTop() + $window.height() * .3,
hitbox_bottom = $window.scrollTop() + $window.height() * .6;
$("li").each(function() {
var $element = $(this),
element_top = $element.offset().top,
element_bottom = $element.offset().top + $element.height();
$element.toggleClass("middle-viewport", hitbox_top < element_bottom && hitbox_bottom > element_top);
});
}, 200);
});
#overlay {
position: fixed;
left: 0;
top: 30%;
width: 100%;
height: 30%;
background-color: rgba(0, 192, 255, .5);
}
ul {
padding: 0;
text-align: center;
}
li {
display: inline-block;
margin: 10px;
width: 200px;
height: 200px;
background-color: #F5F5F5;
}
li.middle-viewport {
background-color: #FF0000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="overlay"></div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
J'étais libre de créer un plugin pour cela. Dans les options, vous pouvez définir des pourcentages, une classe css, un événement déclencheur et un délai d'exécution (css changé en responsive pour la présentation uniquement):
jQuery.fn.extend({
markInViewport: function (options) {
var that = this;
this.defaults = {
percentTop: 30,
percentBottom: 40,
cssClass: 'middleviewport',
event: 'scroll resize',
delay: 10
};
this.options = $.extend(that.defaults, options);
this.win = $(window);
this.delayChecking = null;
this.items = [];
this.checkItems = function (items) {
clearTimeout(that.delayChecking);
that.delayChecking = setTimeout(function () {
var thisWindowHeight = that.win.height();
var thisWindowScrollTop = that.win.scrollTop();
that.items.each(function (j) {
var thisItem = $(this);
var thisItemHeight = thisItem.outerHeight();
var thisItemPositionTop = thisItem.offset().top;
var currentPercentTop = (thisItemPositionTop - thisWindowScrollTop) / thisWindowHeight * 100;
var currentPercentBottom = (thisWindowScrollTop + thisWindowHeight - thisItemPositionTop - thisItemHeight) / thisWindowHeight * 100;
thisItem.toggleClass(that.options.cssClass, currentPercentTop >= that.options.percentTop && currentPercentBottom >= that.options.percentBottom);
});
}, that.options.delay);
};
return this.each(function () {
that.items = that.children();
$(window).on(that.options.event, that.checkItems);
that.checkItems();
});
}
});
$('.check_viewport').markInViewport();
ul {
margin: 0 auto;
padding: 0;
}
ul li {
width: 32.73%;
height: 0;
padding-bottom: 3.5%; /* responsive height */
background: #f5f5f5;
float: left;
margin: .3%;
list-style:none;
}
ul li.middleviewport {
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<ul class="check_viewport">
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li>
</ul>
</body>
Créez une largeur de div width:100%
Et height:100%
Qui représentent la fenêtre. À l'intérieur de cette div, vous placez votre système de grille.
Que vous devez utiliser jquery .position()
position jquery
var grid = $( "griddiv's" );
var position = grid.position();
var height = $('parentdiv').height();
lower = 0.3 * height;
upper = 0.6 * height;
if(grid.top >= lower && grid.top <= upper){
$('gridcell').css('background','red');
}
Je ne l'ai pas testé mais j'espère que ça marche