获取屏幕上最明显的元素

时间:2016-07-13 19:59:51

标签: javascript jquery

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

example

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

我做了一个快速(它不是那么快)的搜索,但无济于事,如果我错过了 - 我的道歉。

4 个答案:

答案 0 :(得分:8)

TLDR:

受到这个问题的启发以及我自己项目中类似功能的必要性,我根据下面的代码撰写了module/jQuery plugin。如果您对' how'不感兴趣,只需下载或安装您最喜爱的软件包管理器即可。

原始答案:

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

&#13;
&#13;
(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 $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);
&#13;
.top {
  height: 900px;
  background-color: #999
}
.middle {
  height: 200px;
  background-color: #eee
}
.bottom {
  height: 600px;
  background-color: #666
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

是的,这个问题太宽泛了。但我有兴趣解决它。 以下是如何实现它的粗略示例。

我试着解释一下评论的内容。肯定可以做得更好,但我希望它有所帮助。

// 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/

答案 2 :(得分:1)

getBoundingClientRect()

可能

added a jQuery plugin

遍历选中的元素并检查

  • 是viewport中的元素吗?
  • 元素的可见高度是什么?
  • 是最明显的元素吗?

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>

答案 3 :(得分:0)

<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]);