admin管理员组

文章数量:1405393

I am having this problem where i have a set of 6 UL's having a mon class x.Each of them consist of a specific section of the page.Now i have 6 menus that are related to each of the section.What i have to do is highlight the menu when its related section is in users view. For this i thought that may be jQuery position(); or offset(); could have helped but they give the top and left of the element.I also tried using jQuery viewport plugin but apparently view port is big it can show more than one UL at a time hence i cant apply element specific logic here.I am not familliar to this but does anything changes of an element on scrolling?If yes then how to access it?

Please share your views.

Regards Himanshu Sharma.

I am having this problem where i have a set of 6 UL's having a mon class x.Each of them consist of a specific section of the page.Now i have 6 menus that are related to each of the section.What i have to do is highlight the menu when its related section is in users view. For this i thought that may be jQuery position(); or offset(); could have helped but they give the top and left of the element.I also tried using jQuery viewport plugin but apparently view port is big it can show more than one UL at a time hence i cant apply element specific logic here.I am not familliar to this but does anything changes of an element on scrolling?If yes then how to access it?

Please share your views.

Regards Himanshu Sharma.

Share Improve this question edited Mar 27, 2012 at 8:28 techie_28 asked Mar 23, 2012 at 4:59 techie_28techie_28 2,1454 gold badges43 silver badges64 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 5 +25

Is very easy to do it using jQuery and a dummy fixed HTML block that helps you find the current position of the viewport.

$(window).on("scroll load",function(){  
    var once = true;
    $(".title").each(function(ele, index){
        if($(this).offset().top > $("#viewport_helper").offset().top && once){              
            var index = $(this).index(".title");
            $(".current").removeClass('current')        
            $("#menu li").eq(index).addClass('current')
            once = false;
        }
    });     
})

Check out a working example: http://jsfiddle/6c8Az/1/


You could also do something similar with the jQuery plugin, together with the :first selector:

$(window).on("scroll load",function(){  
    $(".title:in-viewport:first").each(function(){
        var index = $(this).index(".title");
        $(".current").removeClass('current')        
        $("#menu li").eq(index).addClass('current')
    }); 
})
  1. You can get the viewport's width and height via $(document).width() and $(document).height()
  2. You can get how many pixels user scrolls via $(document).scrollTop() and $(document).scrollLeft
  3. Combining 1 and 2, you can calculate where the viewport rectangle is
  4. You can get the rectangle of an element using $(element).offset(), $(element).width() and $(element).height()
  5. So the only thing left to you is to determine whether the viewport's rectangle contains (or interacts) the elements's rectangle

So the whole code may look like:

/**
 * Check wether outer contains inner
 * You can change this logic to matches what you need
 */
function rectContains(outer, inner) {
    return outer.top <= inner.top &&
        outer.bottom >= inner.bottom &&
        outer.left <= inner.left &&
        outer.right >= inner.right;
}

/**
 * Use this function to find the menu related to <ul> element
 */
function findRelatedMenu(element) {
    return $('#menu-' + element.attr('id'));
}

function whenScroll() {
    var doc = $(document);
    var elem = $(element);
    var viewportRect = {
        top: doc.scrollTop(),
        left: doc.scrollLeft(),
        width: doc.width(),
        height: doc.height()
    };
    viewportRect.bottom = viewportRect.top + viewportRect.height;
    viewportRect.right = viewportRect.left + viewportRect.width;

    var elements = $('ul.your-class');
    for (var i = 0; i < elements.length; i++) {
        var elem = $(elements[i]);
        var elementRect = {
            top: elem.offset().top,
            left: elem.offset().left,
            width: elem.width(),
            height: elem.height()
        };
        elementRect.bottom = elementRect.top + elementRect.height;
        elementRect.right = elementRect.left + elementRect.width;

        if (rectContains(viewportRect, elementRect)) {
            findRelatedMenu(elem).addClass('highlight');
        }
    }
}

$(window).on('scroll', whenScroll);

Let's see if i understood well. You have a page long enough to scroll, and there is an element that when it appears in the viewport, you wanna do something with it. So the only event that's is triggered for sure on the time the element gets in the viewport is the 'scroll'. So if the element is on the page and the scroll is on the viewport, what you need to do is bind an action to the scroll event to check if the element is in the view each time the event is trigger. Pretty much like this:

$(window).scroll(function() {
   check_element_position();
});

Now, in order for you to know if the element is in the viewport, you need 3 things. The offset top of that element, the size of the viewport and the scroll top of the window. Should pretty much look like this:

function check_element_position() {
   var win = $(window);
   var window_height = win.height();
   var element = $(your_element);
   var elem_offset_top = element.offset().top;
   var elem_height = element.height();
   var win_scroll = win.scrollTop();
   var pseudo_offset = (elem_offset_top - win_scroll);
   if (pseudo_offset < window_height && pseudo_offset >= 0) {
      // element in view
   }
   else {
      // elem not in view
   }
}

Here, (elem_offset_top - win_scroll) represent the element position if there was no scroll. Like this, you just have to check if the element offset top is higher then the window viewport to see if it's in view or not. Finally, you could be more precise on you calculations by adding the element height (variable already in there) because the code i just did will fire the event even if the element is visible by only 1 pixels.

Note: I just did that in five minutes so you might have to fix some of this, but this gives you a pretty darn good idea of what's going on ;)

Feel free to ment and ask questions

本文标签: javascriptGetting Coordinates of an element on page scrollStack Overflow