简体   繁体   English

为屏幕上的位置添加侦听器

[英]Adding listener for position on screen

I'd like to set something up on my site where when you scroll within 15% of the bottom of the page an element flyouts from the side... I'm not sure how to get started here... should I add a listener for a scroll function or something? 我想在我的网站上设置一些东西,当你在页面底部的15%内滚动时,一个元素从侧面跳出来...我不知道如何开始这里...我应该添加一个是否有滚动功能的监听器?

I'm trying to recreate the effect at the bottom of this page: http://www.nytimes.com/2011/01/25/world/europe/25moscow.html?_r=1 我正在尝试重新创建此页面底部的效果: http//www.nytimes.com/2011/01/25/world/europe/25moscow.html? _ r = 1

update 更新

I have this code.... 我有这个代码....

     console.log(document.body.scrollTop); //shows 0
     console.log(document.body.scrollHeight * 0.85); //shows 1038.7
     if (document.body.scrollTop > document.body.scrollHeight * 0.85) {
      console.log();
   $('#flyout').animate({
     right: '0'
    },
    5000,
    function() {

   });
     }

the console.log() values aren't changing when I scroll to the bottom of the page. 当我滚动到页面底部时, console.log()值没有改变。 The page is twice as long as my viewport. 该页面是我的视口的两倍。

[ Working Demo ] [ 工作演示 ]

$(document).ready(function () {
  var ROOT = (function () {
    var html = document.documentElement;
    var htmlScrollTop = html.scrollTop++;
    var root = html.scrollTop == htmlScrollTop + 1 ? html : document.body;
    html.scrollTop = htmlScrollTop;
    return root;
  })();

  // may be recalculated on resize
  var limit = (document.body.scrollHeight - $(window).height()) * 0.85;
  var visible = false;
  var last = +new Date;
  $(window).scroll(function () {
    if (+new Date - last > 30) { // more than 30 ms elapsed
      if (visible && ROOT.scrollTop < limit) {
        setTimeout(function () { hide(); visible = false; }, 1);
      } else if (!visible && ROOT.scrollTop > limit) {
        setTimeout(function () { show(); visible = true; }, 1);
      }
      last = +new Date;
    }
  });
});

I know this is an old topic, but the above code that received the check mark was also triggering the $(window).scroll() event listener too many times. 我知道这是一个老话题,但上面收到复选标记的代码也触发了$(window).scroll()事件监听器太多次。

I guess twitter had this same issue at one point. 我猜twitter在某个方面也有同样的问题。 John Resig blogged about it here: http://ejohn.org/blog/learning-from-twitter/ John Resig在这里写了博客: http//ejohn.org/blog/learning-from-twitter/

$(document).ready(function(){
     var ROOT = (function () {
        var html = document.documentElement;
        var htmlScrollTop = html.scrollTop++;
        var root = html.scrollTop == htmlScrollTop + 1 ? html : document.body;
        html.scrollTop = htmlScrollTop;
        return root;
    })();

    // may be recalculated on resize
    var limit = (document.body.scrollHeight - $(window).height()) * 0.85;
    var visible = false;
    var last = +new Date;
    var didScroll = false; 

    $(window).scroll(function(){
        didScroll = true; 
    })

    setInterval(function(){
        if(didScroll){
            didScroll = false; 
            if (visible && ROOT.scrollTop < limit) {
                hideCredit(); 
                visible = false; 
            } else if (!visible && ROOT.scrollTop > limit) {
                showCredit(); 
                visible = true; 
            }
        }
    }, 30);


    function hideCredit(){
        console.log('The hideCredit function has been called.');
    }

    function showCredit(){
        console.log('The showCredit function has been called.');
    }
});

So the difference between the two blocks of code is when and how the timer is called. 因此,两个代码块之间的区别在于调用定时器的时间和方式。 In this code the timer is called off the bat. 在这段代码中,计时器被称为蝙蝠。 So every 30 millaseconds, it checks to see if the page has been scrolled. 因此,每30分钟,它会检查页面是否已滚动。 if it's been scrolled, then it checks to see if we've passed the point on the page where we want to show the hidden content. 如果它已被滚动,那么它会检查我们是否已经通过了我们想要显示隐藏内容的页面上的点。 Then, if that checks true, the actual function then gets called to show the content. 然后,如果检查为true,则调用实际函数以显示内容。 (In my case I've just got a console.log print out in there right now. (在我的情况下,我刚刚在那里打印出一个console.log。

This seems to be better to me than the other solution because the final function only gets called once per iteration. 这似乎比其他解决方案更好,因为最终函数每次迭代只调用一次。 With the other solution, the final function was being called between 4 and 5 times. 使用另一种解决方案,最终的功能被调用4到5次。 That's got to be saving resources. 这必须节省资源。 But maybe I'm missing something. 但也许我错过了一些东西。

bad idea to capture the scroll event, best to use a timer and every few milliseconds check the scroll position and if in the range you need then execute the necessary code for what you need 抓住滚动事件的好主意,最好使用计时器,每隔几毫秒检查滚动位置,如果在你需要的范围内,那么执行你需要的必要代码

Update: in the past few years the best practice is to subscribe to the event and use a throttle avoiding excessive processing https://lodash.com/docs#throttle 更新:在过去几年中,最佳做法是订阅活动并使用throttle避免过度处理https://lodash.com/docs#throttle

Something like this should work: 这样的事情应该有效:

$(window).scroll(function() {
    if (document.body.scrollTop > document.body.scrollHeight * 0.85) {
        // flyout
    }
});

document.body.scrollTop may not work equally well on all browsers (it actually depends on browser and doctype); document.body.scrollTop在所有浏览器上可能无法正常工作(它实际上取决于浏览器和doctype); so we need to abstract that in a function. 所以我们需要在函数中抽象出来。

Also, we need to flyout only one time. 此外,我们只需要飞行一次。 So we can unbind the event handler after having flyed out. 所以我们可以在飞出后取消绑定事件处理程序。

And we don't want the flyout effect to slow down scrolling, so we will run our flytout function out of the event loop (by using setTimeout()). 我们不希望弹出效果减慢滚动速度,因此我们将从事件循环中运行我们的flytout函数(通过使用setTimeout())。

Here is the final code: 这是最终的代码:

// we bind the scroll event, with the 'flyout' namespace
// so we can unbind easily
$(window).bind('scroll.flyout', (function() {

    // this function is defined only once
    // it is private to our event handler
    function getScrollTop() {
        // if one of these values evaluates to false, this picks the other
        return (document.documentElement.scrollTop||document.body.scrollTop);
    }

    // this is the actual event handler
    // it has the getScrollTop() in its scope
    return function() {
        if (getScrollTop() > (document.body.scrollHeight-$(window).height()) * 0.85) {
            // flyout
            // out of the event loop
            setTimeout(function() {
                alert('flyout!');
            }, 1);

            // unbind the event handler
            // so that it's not call anymore
            $(this).unbind('scroll.flyout');
        }
    };
})());

So in the end, only getScrollTop() > document.body.scrollHeight * 0.85 is executed at each scroll event, which is acceptable. 所以最后,只有getScrollTop() > document.body.scrollHeight * 0.85在每个滚动事件中执行,这是可以接受的。

The flyout effect is ran only one time, and after the event has returned, so it won't affect scrolling. 弹出效果仅运行一次,并且在事件返回后,因此不会影响滚动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM