检查元素是否在视口的30%到60%之间

时间:2015-04-27 09:16:18

标签: javascript jquery html css viewport

我正在尝试更改<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;
}

5 个答案:

答案 0 :(得分:29)

  1. scroll
  2. 上使用window事件处理程序
  3. 遍历所有li元素以检查元素是否在感兴趣的视口中
  4. li获取top位置,并检查它是否在感兴趣的视口部分。
  5. Demo:

    为了演示目的,更改了li的高度。

    请参阅代码中的内联注释。

    &#13;
    &#13;
    $(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');
          }
        });
      });
    });
    &#13;
    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;
    }
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:7)

改进了@Tushar的解决方案,即使在调整窗口大小后也能使其工作(每次都需要重新计算视口,而不仅仅是在开始时),并使其开始已经突出显示,而无需滚动。

还改进了示例图形以突出显示感兴趣的区域。

Running demo

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

答案 2 :(得分:1)

[[此示例检查元素的任何部分是否在指定区域内]]

如果您有两个方框的顶部和底部坐标,则可以通过检查来检查两个框是否重叠:

if(model[0][0] ==9)

在以下示例中,box1是窗口的30%-60%部分,而box2是每个列表项。添加去抖功能,我们有:

box1.top < box2.bottom && box1.bottom > box2.top
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;
}

答案 3 :(得分:0)

创建代表视口的div宽度width:100%height:100%。在这个div里面放置你的网格系统。

您需要使用jquery .position() jquery position

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');
}

我没有测试它,但我希望它有效

答案 4 :(得分:0)

我可以自由地为此创建一个插件。在选项中,您可以设置百分比,css类,触发事件和执行延迟(css更改为仅对演示文稿响应):

&#13;
&#13;
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();
&#13;
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;
}
&#13;
<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>
&#13;
&#13;
&#13;

<强> Fiddle here