Check if element is between 30% and 60% of the viewport

前端 未结 5 496
轻奢々
轻奢々 2020-11-30 03:28

I am trying to change the color of

  • elements when they are between 30% and 60% of the viewport.

    So I have this grid of elements stacking side

  • 相关标签:
    5条回答
    • 2020-11-30 03:33

      Create a div width width:100% and height:100% that represent the viewport. Inside this div you place your grid system.

      Than you need to use 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');
      }
      

      I didn't test it but I hope it works

      0 讨论(0)
    • 2020-11-30 03:42

      I was free to create a plugin for this. Within options you can set percents, css class, trigger event and execution delay (css changed to responsive for presentation only):

      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>

      Fiddle here

      0 讨论(0)
    • 2020-11-30 03:51
      1. Use scroll event handler on window
      2. Loop over all the li elements to check if the element is in the interested viewport
      3. Get the li position from top and check if it is in the interested viewport section.

      Demo:

      Changed the height of li for demo purpose.

      See the comments inline in the code.

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

      0 讨论(0)
    • 2020-11-30 03:53

      [[ This example checks if ANY part of the element is inside the specified region ]]

      When you have the top and bottom coordinates of two boxes, you can check if the two boxes overlap by checking:

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

      In the following example, box1 is the 30%-60% portion of window while box2 is each list item. Add debounce function and we have:

      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>

      0 讨论(0)
    • 2020-11-30 03:55

      Improved @Tushar's solution to make it work even after a resize of the window (a recalculation of the viewport is necessary each time, not only at the beginning), and to make it start already highlighted, without the need to scroll.

      Also improved a bit the graphic of the example to highlight the interested area.

      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>

      0 讨论(0)
    提交回复
    热议问题