How to select the last element on viewport

折月煮酒 提交于 2020-04-29 10:09:09

问题


I'm looking for an effecient way to constantly select the last element within the visible window/viewport.

So far, this is my code:

$(window).scroll(function () { 

$('.post-content p').removeClass("temp last")
$('.post-content p').filter(":onScreen").addClass("temp")

$(".temp").eq(-1).addClass("last")

    });

As you could probably imagine, this hauls up a lot of resources and doesn't perform very well. Can somebody please suggest from more elegant code?

My knowledge of Javascript is very basic, so please be patient with me. Thank you.

PS: I am using the onScreen plugin for the :onScreen selector: http://benpickles.github.com/onScreen/


回答1:


Binding the scroll handler

Binding functions to the scroll Event can lead to serious performance problems. The scroll event fires really vigorously on page scroll, so binding functions with resource-heavy code to it is a bad idea.

What John suggests is setting up the interval and thereby having the code only execute some time after a scroll event.

Have a look at this jsfiddle to see difference between the implementations

The indirect handler solution comes at the cost of a noticeable lag between scrolling and executing the code, and it is your decision if you can trade in performance for snappier execution. Be sure to test performance on every browser you support.

Speeding up code execution

There are a lot of different concepts you can use to speed up your code. Regarding your code, it comes down to:

  • Caching selectors. You reselect elements every time the scroll handler fires, which is unnecessary
  • Not using jQuery plugins without knowing what they do. In your case, the plugin code is nice and quite straightforward, but for your goal you can have even snappier code.
  • preventing any unnecessary calculation. With your and the plugin's code, the offset of every element is calculated every time the scroll handler fires.

So what I've come up with is a Jsfiddle with an example how you could do you scroll handler. It's not exactly matched to your DOM because I don't know your html, but it should be easy to match it to your implementation.

I managed to reduce the time used by 95% compared to your code. You can see for yourself by profiling the two samples in chrome.

I assumed you just want to select the last element and you do not need the temp class

So, here's the code with explanations

// Store the offsets in an array
var offsets = [];
// Cache the elements to select
var elements = $('.elem');
// Cache the window jQuery Object
var jWindow = $(window);
// Cache the calculation of the window height
var jWindowHeight = jWindow.height();
// set up the variable for the current selected offset
var currentOffset;
// set up the variable for the current scrollOffset
var scrollOffset;
// set up the variable for scrolled, set it to true to be able to assign at
// the beginning
var scrolled = true;

// function to assign the different elements offsets,
// they don't change on scroll
var assignOffsets = function() {
    elements.each(function() {
        offsets.push({
            offsetTop: $(this).offset().top,
            height: $(this).height(),
            element: $(this)
        });
    });
};

// execute the function once. Exectue it again if you added
// or removed elements
assignOffsets();

// function to assign a class to the last element
var assignLast = function() {
    // only execute it if the user scrolled
    if (scrolled) {
        // assigning false to scrolled to prevent execution until the user
        // scrolled again
        scrolled = false;

        // assign the scrolloffset
        scrollOffset = jWindowHeight + jWindow.scrollTop();

        // only execute the function if no current offset is set,
        // or the user scrolled down or up enough for another element to be
        // the last
        if (!currentOffset || currentOffset.offsetTop < scrollOffset || currentOffset.offsetTop + currentOffset.height > scrollOffset) {

            // Iterate starting from the bottom
            // change this to positive iteration if the elements count below 
            // the fold is higher than above the fold
            for (var i = offsets.length - 1; i >= 0; i--) {

                // if the element is above the fold, reassign the current
                // element
                if (offsets[i].offsetTop + offsets[i].height < (scrollOffset)) {
                    currentOffset && (currentOffset.element.removeClass('last'));
                    currentOffset = offsets[i];
                    currentOffset.element.addClass('last');
                    // no further iteration needed and we can break;
                    break;
                }
            }
            return true;
        } else {
            return false;
        }
    }
}

assignLast();

// reassign the window height on resize;
jWindow.on('resize', function() {
    jWindowHeight = jWindow.height();
});

// scroll handler only doing assignment of scrolled variable to true
jWindow.scroll(function() {
    scrolled = true;
});

// set the interval for the handler
setInterval(assignLast, 250);

// assigning the classes for the first time
assignLast();


来源:https://stackoverflow.com/questions/11598138/how-to-select-the-last-element-on-viewport

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!