【问题标题】:Get the element which is the most visible on the screen获取屏幕上最明显的元素
【发布时间】:2016-11-16 13:44:15
【问题描述】:

我想获得屏幕上最明显的一个元素(占用最多空间)。我在下面添加了一张示例图片,以进一步了解我的问题。

两个黑色边框是屏幕的两侧。如您所见,绿色框 (div2) 是屏幕上最明显的 - 我想知道如何获取该元素。最可见的元素不必完全可见。

我已经进行了快速(不是那么快)搜索,但无济于事,如果我错过了 - 抱歉。

【问题讨论】:

  • 你可以得到它们的clientheight,减去它们的差值,然后拍一张高度大于的图片
  • 这不是微不足道的,如果没有您的任何代码,它就会成为一个过于宽泛的问题。该站点的工作原理是您提供一些未按预期执行的代码,而其他代码则帮助修复该代码....不是从头开始编写代码或提供有关做什么的教程
  • 你有没有尝试过。发布您的代码。 SO 不是代码编写服务。
  • 我很想看看你最终得到什么答案。我也不知道该怎么做。对于那些想要解决这个问题的人:我不明白“您需要代码才能向 SO 发布问题”。一个宽泛的问题也许只需要一个宽泛的答案?
  • 您可能会发现jQuery.fracs 很有用。

标签: javascript jquery


【解决方案1】:

TLDR:

受这个问题和我自己的项目中类似功能的必要性的启发,我根据下面的代码编写了module/jQuery plugin。如果您对“方法”不感兴趣,只需下载它或使用您最喜欢的包管理器安装即可。

原答案:

answer provided by exabyssus 在大多数情况下都能正常工作,除非元素的顶部或底部都不可见,例如当元素高度大于窗口高度时。

这是一个更新版本,它考虑了这种情况并使用getBoundingClientRect,即supported right the way down to IE8

// Usage: var $element = getMostVisible($('.elements' ));
function getMostVisible($elements) {
    var element,
        viewportHeight = $(window).height(),
        max = 0;

    $elements.each(function() {
        var visiblePx = getVisibleHeightPx($(this), viewportHeight);

        if (visiblePx > max) {
            max = visiblePx;
            element = this;
        }
    });

    return $elements.filter(element);
}

function getVisibleHeightPx($element, viewportHeight) {
    var rect = $element.get(0).getBoundingClientRect(),
        height = rect.bottom - rect.top,
        visible = {
            top: rect.top >= 0 && rect.top < viewportHeight,
            bottom: rect.bottom > 0 && rect.bottom < viewportHeight
        },
        visiblePx = 0;

    if (visible.top && visible.bottom) {
        // Whole element is visible
        visiblePx = height;
    } else if (visible.top) {
        visiblePx = viewportHeight - rect.top;
    } else if (visible.bottom) {
        visiblePx = rect.bottom;
    } else if (height > viewportHeight && rect.top < 0) {
        var absTop = Math.abs(rect.top);

        if (absTop < height) {
            // Part of the element is visible
            visiblePx = height - absTop;
        }
    }

    return visiblePx;
}

这会根据像素返回最可见的元素,而不是元素高度的百分比,这非常适合我的用例。如果需要,可以轻松修改它以返回百分比。

您也可以将其用作 jQuery 插件,这样您就可以使用 $('.elements').mostVisible() 获取最可见的元素,而不是将元素传递给函数。为此,您只需将其包含在上面的两个函数中:

$.fn.mostVisible = function() {
    return getMostVisible(this);
};

有了它,您可以链接您的方法调用,而不必将元素保存到变量中:

$('.elements').mostVisible().addClass('most-visible').html('I am most visible!');

所有内容都包含在一个小演示中,您可以在 SO 上试用:

(function($) {
  'use strict';

  $(function() {
    $(window).on('scroll', function() {
      $('.the-divs div').html('').removeClass('most-visible').mostVisible().addClass('most-visible').html('I am most visible!');
    });
  });

  function getMostVisible($elements) {
    var element,
      viewportHeight = $(window).height(),
      max = 0;

    $elements.each(function() {
      var visiblePx = getVisibleHeightPx($(this), viewportHeight);

      if (visiblePx > max) {
        max = visiblePx;
        element = this;
      }
    });

    return $elements.filter(element);
  }

  function getVisibleHeightPx($element, viewportHeight) {
    var rect = $element.get(0).getBoundingClientRect(),
      height = rect.bottom - rect.top,
      visible = {
        top: rect.top >= 0 && rect.top < viewportHeight,
        bottom: rect.bottom > 0 && rect.bottom < viewportHeight
      },
      visiblePx = 0;

    if (visible.top && visible.bottom) {
      // Whole element is visible
      visiblePx = height;
    } else if (visible.top) {
      visiblePx = viewportHeight - rect.top;
    } else if (visible.bottom) {
      visiblePx = rect.bottom;
    } else if (height > viewportHeight && rect.top < 0) {
      var absTop = Math.abs(rect.top);

      if (absTop < height) {
        // Part of the element is visible
        visiblePx = height - absTop;
      }
    }

    return visiblePx;
  }



  $.fn.mostVisible = function() {
    return getMostVisible(this);
  }

})(jQuery);
.top {
  height: 900px;
  background-color: #999
}

.middle {
  height: 200px;
  background-color: #eee
}

.bottom {
  height: 600px;
  background-color: #666
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="the-divs">
  <div class="top"></div>
  <div class="middle"></div>
  <div class="bottom"></div>
</div>

【讨论】:

    【解决方案2】:

    是的,这个问题太宽泛了。但我有兴趣解决它。 这是有关如何完成它的粗略示例。

    我试图解释 cmets 发生了什么。当然可以做得更好,但我希望它有所帮助。

    // init on page ready
    $(function() {
        // check on each scroll event
        $(window).scroll(function(){
            // elements to be tested
            var _elements = $('.ele');
    
            // get most visible element (result)
            var ele = findMostVisible(_elements);
        });
    });
    
    
    function findMostVisible(_elements) {
    
        // find window top and bottom position.
        var wtop = $(window).scrollTop();
        var wbottom = wtop + $(window).height();
    
    
        var max = 0; // use to store value for testing
        var maxEle = false; // use to store most visible element
    
        // find percentage visible of each element
        _elements.each(function(){
    
            // get top and bottom position of the current element
            var top = $(this).offset().top;
            var bottom = top + $(this).height();
    
            // get percentage of the current element
            var cur = eleVisible(top, bottom, wtop, wbottom);
    
            // if current element is more visible than previous, change maxEle and test value, max 
            if(cur > max) {
                max = cur;
                maxEle = $(this);
            }
        });
    
        return maxEle;
    }
    
    // find visible percentage
    function eleVisible(top, bottom, wtop, wbottom) {
    
        var wheight = wbottom - wtop;
    
        // both bottom and top is vissible, so 100%
        if(top > wtop && top < wbottom && bottom > wtop && bottom < wbottom)
        {
            return 100;
        }
    
        // only top is visible
        if(top > wtop && top < wbottom)
        {
            return  100 + (wtop - top) / wheight * 100;
        }
    
        // only bottom is visible
        if(bottom > wtop && bottom < wbottom)
        {
            return  100 + (bottom - wbottom) / wheight * 100;
        }
    
        // element is not visible
        return 0;
    }
    

    工作示例 - https://jsfiddle.net/exabyssus/6o30sL24/

    【讨论】:

    • 有时 maxEle 是一个布尔值,有时它是一个元素。这是你的意图吗?
    • @bhspencer 是一个错误,如果没有元素是可见的,则 maxEle 为 false,如果存在则为 element
    • 我添加了一个工作示例,希望对您有所帮助。 jsfiddle.net/exabyssus/6o30sL24
    • 这是完美的,绝对是我想要的。非常感谢!
    • 我知道这个答案是旧的,但对于像我这样从谷歌偶然发现它的任何人:eleVisible 函数错误地返回 0 对于顶部或底部都不可见的任何元素(即元素高度大于窗口高度)
    【解决方案3】:

    getBoundingClientRect() 可能

    added a jQuery plugin

    遍历选择的元素并检查

    • 元素在视口中吗?
    • 元素的可见高度是多少?
    • 元素是最明显的元素吗?

    function getMostVisibleElement(selector) {
        var clientRect = null;
        var clientRectTop = 0;
        var maxVisibleHeight = 0;
        var visibleHeightOfElem = 0;
        var mostVisibleElement = null;
        var skipRest = false;
    
        var visibleElems = $(selector).each(function(i, element) {
            if (skipRest === false) {
                clientRect = element.getBoundingClientRect();
                clientRectTop = Math.abs(clientRect.top);
    
                if (clientRect.top >= 0) {
                    visibleHeightOfElem = window.innerHeight - clientRectTop;
                } else {
                    visibleHeightOfElem = clientRect.height - clientRectTop;
                }
    
                if (visibleHeightOfElem >= clientRect.height) {
                    mostVisibleElement = element;
                    skipRest = true;
                } else {
    
                    if (visibleHeightOfElem > maxVisibleHeight) {
                        maxVisibleHeight = visibleHeightOfElem;
                        mostVisibleElement = element;
                    }
                }
    
            }
        });
        return mostVisibleElement;
    }
    
    $(window).on('click', function() {
        var mostVisible = getMostVisibleElement('.my-container');
        $(mostVisible).addClass('highlighted');
        
        setTimeout(function() {
          $(mostVisible).removeClass('highlighted');
        }, 200);
        // alert(mostVisible.id)
    });
    .my-container {
      height: 100vh;
    }
    
    #a {
      background: #007bff;
    }
    
    #b {
      background: #28a745;
      height: 70vh;
    }
    
    #c {
      background: #ffc107;
    }
    
    #d {
      background: #17a2b8;
    }
    
    .highlighted {
      background: #dc3545 !important; 
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="my-container" id="a"></div>
    <div class="my-container" id="b"></div>
    <div class="my-container" id="c"></div>
    <div class="my-container" id="d"></div>

    【讨论】:

      【解决方案4】:
      <style>
          .block{
              padding: 20px;
              border:2px solid #000;
              height: 200px;
              overflow:hidden;
          }
          .green{
              border: 1px solid green;
              height: 150px;
              margin:20px 0px;
          }
          .red{
              border: 1px solid red;
              height: 100px;
          }
      </style>
      <div class="block">
          <div class="example green"></div>
          <div class="example red"></div>
      </div>
      
      
      var divs = $('.example');
      var obj = {};
      var heights = [];
      
      $.each(divs,function (key, val)
      {
          heights.push($(val).outerHeight());
          obj[$(val).outerHeight()] = $(val);
      });
      var max = Math.max.apply(null, heights);
      
      console.log(obj[max]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-20
        • 2023-02-26
        • 2011-08-15
        • 2018-03-11
        • 2020-03-19
        • 1970-01-01
        • 2017-10-31
        • 2019-11-14
        相关资源
        最近更新 更多