2011-01-26 4 views
8

내 사이트에서 뭔가를 설정하고 싶습니다. 페이지 하단의 15 % 내에서 측면에서 요소 플라이 아웃을 스크롤 할 때 ... 잘 모르겠습니다. 여기에서 시작되었습니다 ... 스크롤 기능이나 기타 리스너를 추가해야합니까?화면상의 위치에 청취자 추가하기

나는이 페이지 하단의 효과를 재현하기 위해 노력하고있어 : http://www.nytimes.com/2011/01/25/world/europe/25moscow.html?_r=1

업데이 트를

나는 ....

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

    }); 
    } 

console.log() 값이 코드를 때로 믿을 수있다 페이지의 맨 아래로 스크롤하면 변경되지 않습니다. 페이지가 내 뷰포트의 두 배입니다. 과거에 :

+0

이것은 브라우저와 doctype에 따라 다르며 또한 document.documentElement.scrollTop을 사용하여 시도하십시오. '(document.documentElement.scrollTop || document.body.scrollTop)'가 작동 할 수도 있습니다. – arnaud576875

답변

6

는 [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; 
    } 
    }); 
}); 
+0

상자가 숨겨지기 전에 페이지의 맨 아래로 스크롤 한 다음 맨 위로 이동 한 다음 맨 아래로 이동하면 맨 아래에 있더라도 상자는 숨겨진 상태로 유지됩니다. – skibulk

3

나쁜 생각의 범위는 당신이 다음

업데이트를 필요에 필요한 코드를 실행해야하는 경우 가장 타이머 모든 몇 밀리 초를 사용하는 스크롤 위치를 확인하고, 스크롤 이벤트를 캡처

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

document.body.scrollTop : 몇 년 동안 가장 좋은 방법은 이벤트에 등록하고이 같은 https://lodash.com/docs#throttle

+0

타이머를 계속 실행하는 것은 비용이 많이 소요되므로 피해야합니다. 이벤트에보다 효과적으로 대처할 수 있습니다. –

+0

지난 몇 년 동안 전적으로 당신과 동의합니다. 가장 좋은 방법은 이벤트에 가입하고 ' 스로틀 과도한 처리 방지 https://lodash.com/docs#throttle –

3

뭔가 일을해야 과도한 처리 피하는 throttle을 사용하는 것입니다 모든 브라우저에서 똑같이 잘 작동하지 않을 수도 있습니다 (브라우저 및 doctype에 따라 다릅니다). 그래서 우리는 그것을 함수에서 추상화 할 필요가 있습니다.

또한 플라이 아웃 만 필요합니다. 그래서 우리는 날아간 후에 이벤트 핸들러를 바인딩 해제 할 수 있습니다.

플라이 아웃 효과가 스크롤을 느리게하기를 원하지 않으므로 setTimeout()을 사용하여 이벤트 루프 밖으로 플라이 아웃 기능을 실행합니다.

// 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'); 
     } 
    }; 
})()); 

그래서 결국 getScrollTop() > document.body.scrollHeight * 0.85 만이 허용되는 각각의 스크롤 이벤트 실행된다 :

여기에 최종의 코드이다.

플라이 아웃 효과는 한 번만 실행되고 이벤트가 반환 된 후에는 스크롤에 영향을 미치지 않습니다.

+0

다른 스레드에서 호출되는 별도의 함수로 작업을 수행하면 스크롤에 영향을주지 않습니다. 예를 들어 window.setTimeout (flyout, 0)을 지정하면 스크롤이 끝난 다음 플라이 아웃이 끝납니다. –

+0

네 번째 예제 코드가 보여주는 것입니다 :-) – arnaud576875

+0

은 scrollTop을 가져 오기위한 이식 가능한 함수로 답변을 업데이트했습니다. – arnaud576875

5

나는이 오래된 주제 알지만, 체크 표시를받은 위의 코드는 또한 $(window).scroll() 이벤트 리스너에게 너무 많은 시간을 유발했다.

트위터가 한 번에 같은 문제가 있었던 것 같습니다. 존 레식은 여기에 대해 블로그 : 언제, 어떻게 타이머를 호출

$(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.'); 
    } 
}); 

http://ejohn.org/blog/learning-from-twitter/ 그래서 코드의 두 블록 사이의 차이입니다. 이 코드에서 타이머는 박쥐에서 호출됩니다. 따라서 매 30 밀리 초마다 페이지가 스크롤되었는지 확인합니다.스크롤 된 경우 숨겨진 콘텐츠를 표시 할 페이지의 지점을 통과했는지 확인합니다. 그런 다음 해당 내용이 참이면 실제 함수가 호출되어 내용을 표시합니다. (제 경우에는 방금 console.log 출력을했습니다.

다른 솔루션보다 나을 것 같습니다. 왜냐하면 최종 함수는 반복마다 한 번 호출되기 때문입니다. 다른 솔루션 마지막 함수는 4 번에서 5 번 사이 호출되었습니다. 리소스를 절약해야합니다.하지만 어쩌면 누락 된 것이 있습니다.

+0

위대한 "트위터에서 배우기"기사 – Ant

+0

스크롤이 간격을 시작하고 끝나는 스크롤로 끝내면이 기능이 향상됩니다. 그런 다음 간격 기능이 항상 켜져있는 것은 아닙니다. – Greg

+0

당신이 말하는 개념은 "debounce"입니다. http://davidwalsh.name/javascript-debounce-function – skibulk

관련 문제