How to check if an element is off-screen

后端 未结 7 1847
太阳男子
太阳男子 2020-11-27 11:39

I need to check with jQuery if a DIV element is not falling off-screen. The elements are visible and displayed according CSS attributes, but they could be intentionally plac

7条回答
  •  广开言路
    2020-11-27 11:58

    Well... I've found some issues in every proposed solution here.

    • You should be able to choose if you want entire element to be on screen or just any part of it
    • Proposed solutions fails if element is higher/wider than window and kinda covers browser window.

    Here is my solution that include jQuery .fn instance function and expression. I've created more variables inside my function than I could, but for complex logical problem I like to divide it into smaller, clearly named pieces.

    I'm using getBoundingClientRect method that returns element position relatively to the viewport so I don't need to care about scroll position

    Useage:

    $(".some-element").filter(":onscreen").doSomething();
    $(".some-element").filter(":entireonscreen").doSomething();
    $(".some-element").isOnScreen(); // true / false
    $(".some-element").isOnScreen(true); // true / false (partially on screen)
    $(".some-element").is(":onscreen"); // true / false (partially on screen)
    $(".some-element").is(":entireonscreen"); // true / false 
    

    Source:

    $.fn.isOnScreen = function(partial){
    
        //let's be sure we're checking only one element (in case function is called on set)
        var t = $(this).first();
    
        //we're using getBoundingClientRect to get position of element relative to viewport
        //so we dont need to care about scroll position
        var box = t[0].getBoundingClientRect();
    
        //let's save window size
        var win = {
            h : $(window).height(),
            w : $(window).width()
        };
    
        //now we check against edges of element
    
        //firstly we check one axis
        //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
        var topEdgeInRange = box.top >= 0 && box.top <= win.h;
        var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;
    
        var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
        var rightEdgeInRange = box.right >= 0 && box.right <= win.w;
    
    
        //here we check if element is bigger then window and 'covers' the screen in given axis
        var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
        var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;
    
        //now we check 2nd axis
        var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
        var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    
        var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
        var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    
        //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
        var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
        var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;
    
        return partial ? isPartiallyOnScreen : isEntirelyOnScreen;
    
    };
    
    $.expr.filters.onscreen = function(elem) {
      return $(elem).isOnScreen(true);
    };
    
    $.expr.filters.entireonscreen = function(elem) {
      return $(elem).isOnScreen(true);
    };
    

提交回复
热议问题