Подтвердить что ты не робот

Проверьте, находится ли элемент между 30% и 60% окна просмотра

Я пытаюсь изменить цвет элементов <li>, когда они находятся между 30% и 60% окна просмотра.

Итак, у меня есть эта сетка элементов, расположенных рядом друг с другом следующим образом:

elements stacking side by side

Я столкнулся с несколькими плагинами, такими как Waypoints, Viewport Checker и несколькими другими, но ничего хорошего.

Любая идея?

Я использую довольно простую структуру:

JSFIDDLE

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;
}
4b9b3361

Ответ 1

  • Используйте scroll обработчик событий window
  • Перебирать все элементы li для проверки того, находится ли элемент в интересующем окне просмотра
  • Получить li позицию из top и проверить, находится ли она в интересующем разделе видового экрана.

Демо:

Изменена высота li для демонстрационной цели.

См. комментарии в тексте в коде.

$(document).ready(function() {
  // Get viewport height, gridTop and gridBottom
  var windowHeight = $(window).height(),
    gridTop = windowHeight * .3,
    gridBottom = windowHeight * .6;

  $(window).on('scroll', function() {
    // On each scroll check if `li` is in interested viewport
    $('ul li').each(function() {
      var thisTop = $(this).offset().top - $(window).scrollTop(); // Get the `top` of this `li`

      // Check if this element is in the interested viewport
      if (thisTop >= gridTop && (thisTop + $(this).height()) <= gridBottom) {
        $(this).css('background', 'red');
      } else {
        $(this).css('background', 'gray');
      }
    });
  });
});
ul {
  margin: 0;
  list-style-type: none;
  padding: 0;
}
ul li {
  width: 50px;
  height: 30px;
  background: #f5f5f5;
  float: left;
  margin: 10px;
  text-align: center;
  padding-top: 10px
}
ul li.middleviewport {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
  <li>11</li>
  <li>12</li>
  <li>13</li>
  <li>14</li>
  <li>15</li>
  <li>16</li>
  <li>17</li>
  <li>18</li>
  <li>19</li>
  <li>20</li>
</ul>

Ответ 2

Улучшено решение @Tushar, чтобы оно работало даже после изменения размера окна (пересчет окна просмотра необходим каждый раз, причем не только в начале), и чтобы он начинался уже выделен, без необходимости прокрутки.

Также немного улучшена графика примера, чтобы выделить интересующую область.

Запуск демо

$(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>

Ответ 3

[[В этом примере проверяется, находится ли какая-либо часть элемента внутри указанной области]]

Если у вас есть верхняя и нижняя координаты двух полей, вы можете проверить, перекрываются ли эти два поля, проверив:

box1.top < box2.bottom && box1.bottom > box2.top

В следующем примере box1 - это 30% -60% часть окна, а box2 - каждый элемент списка. Добавьте функцию debounce, и у нас есть:

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>

Ответ 4

Создайте ширину div width:100% и height:100%, которые представляют окно просмотра. Внутри этого div вы помещаете свою сетку.

Чем вам нужно использовать jquery .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');
}

Я не тестировал его, но надеюсь, что он работает

Ответ 5

Я был свободен для создания плагина для этого. В пределах опций вы можете установить проценты, класс css, событие триггера и задержку выполнения (css изменен для реагирования только на презентацию):

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>