如何选择视口上的最后一个元素 [英] How to select the last element on viewport

查看:54
本文介绍了如何选择视口上的最后一个元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种有效的方法来不断选择可见窗口/视口中的最后一个元素.

到目前为止,这是我的代码:

  $(window).scroll(function(){$('.post-content p').removeClass("temp last")$('.post-content p').filter(:onScreen").addClass("temp")$(.temp").eq(-1).addClass("last")}); 

您可能会想像,这会占用大量资源,并且效果不佳.有人可以从更优雅的代码中提出建议吗?

我对Java语言的知识非常基础,因此请耐心等待.谢谢.

PS:我正在将onScreen插件用于:onScreen选择器: http://benpickles.github.com/onScreen/

解决方案

绑定滚动处理程序

将功能绑定到滚动事件会导致严重的性能问题.scroll事件在页面滚动时会非常剧烈地触发,因此将具有大量资源的代码绑定到函数是一个坏主意.

John建议的是设置时间间隔,从而使代码仅在滚动事件之后的某个时间执行.

看看这个jsfiddle来了解实现之间的区别

间接处理程序解决方案的代价是在滚动和执行代码之间存在明显的滞后,这取决于您是否可以为执行快照程序而牺牲性能.请确保在您支持的每种浏览器上测试性能.

加快代码执行速度

您可以使用许多不同的概念来加快代码的速度.关于您的代码,它归结为:

  • 缓存选择器.每次触发滚动处理程序时,您都可以重新选择元素,这是不必要的
  • 在不知道其用途的情况下不使用jQuery插件.在您的情况下,插件代码很好,也很简单,但这只是为了您的目标您甚至可以拥有更简练的代码.
  • 防止任何不必要的计算.使用您和插件的代码,每次滚动处理程序触发时都会计算每个元素的偏移量.

因此,我想出的是 一个Jsfiddle,并提供了一个示例如何滚动处理程序 .它与您的DOM并不完全匹配,因为我不知道您的html,但是将其与您的实现进行匹配应该很容易.

您的代码相比,我设法节省了95%的时间.您可以通过在chrome中对两个样本进行分析来亲自查看.

我假设您只是想选择最后一个元素,并且不需要临时类

所以,这是带有解释的代码

 //将偏移量存储在数组中var offsets = [];//缓存要选择的元素var elements = $('.elem');//缓存窗口jQuery对象var jWindow = $(window);//缓存窗口高度的计算var jWindowHeight = jWindow.height();//为当前选定的偏移量设置变量var currentOffset;//为当前的scrollOffset设置变量var scrollOffset;//设置要滚动的变量,将其设置为true以便能够在//开始var scrolled = true;//用于分配不同元素的偏移量的函数//它们不会滚动变化var AssignOffsets = function(){elements.each(function(){offsets.push({offsetTop:$(this).offset().top,高度:$(this).height(),元素:$(this)});});};//执行一次该函数.如果添加,请再次执行//或删除的元素AssignOffsets();//为最后一个元素分配一个类的函数var AssignLast = function(){//仅在用户滚动时执行如果(滚动){//将false分配给滚动以阻止执行,直到用户//再次滚动滚动=假;//分配scrolloffsetscrollOffset = jWindowHeight + jWindow.scrollTop();//仅在未设置当前偏移量的情况下执行该函数,//或用户向下滚动或向上滚动足以使另一个元素成为//最后如果(!currentOffset || currentOffset.offsetTop< scrollOffset || currentOffset.offsetTop + currentOffset.height> scrollOffset){//从底部开始迭代//如果元素计数在以下,则将其更改为正迭代//折痕高于折痕for(var i = offsets.length-1; i> = 0; i--){//如果元素在折叠上方,则重新分配当前元素//元素if(offsets [i] .offsetTop + offsets [i] .height<(scrollOffset)){currentOffset&&(currentOffset.element.removeClass('last'));currentOffset =偏移量[i];currentOffset.element.addClass('last');//不需要进一步的迭代,我们可以中断;休息;}}返回true;} 别的 {返回false;}}}AssignLast();//在调整大小时重新分配窗口高度;jWindow.on('resize',function(){jWindowHeight = jWindow.height();});//滚动处理程序仅将滚动变量分配为truejWindow.scroll(function(){滚动= true;});//设置处理程序的间隔setInterval(assignLast,250);//第一次分配类AssignLast(); 

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/

解决方案

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

这篇关于如何选择视口上的最后一个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆