1

我为我的个人主页编写了一个插件,它应该滚动浏览一系列元素,捕捉到每个元素 offsetTop。
我正在使用requestanimationframe来消除滚动事件,但有时会跳过幻灯片,我就是不知道为什么。此外,在 Chrome 和 Safari 上,我遇到了window.pageYOffset的问题可能小于 0 并且大于文档高度,因为这些浏览器在 mac(带有触摸板)上使用了某种缓和功能——你将如何处理?

这是代码:

// requerstanimationframe for all browsers
window.rAF = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function( callback ){
                window.setTimeout(callback, 1000 / 60);
              };
    })();

// main plugin code
var Slides = {

    el: ".slide",
    arrowUp: $(".btn-previous"),
    arrowDown: $(".btn-next"),
    lastSlide: 0,
    lastY: 0,
    scrolling: false,
    scrollSpeed: 500,

    init: function(){

        this.$elem = $(this.el);
        this.catchSlides();
        this.newPos(true);

        // event handler
        this.registerHandler();

        return this;
    },

    registerHandler: function(){
        var that = this,
            handler = {
            "resize.slider": jQuery.proxy(this.onResize,this),
            "scroll.slider": jQuery.proxy(this.onScroll,this),
            "keydown.slider": jQuery.proxy(this.keyhandler,this),
            "mousedown.slider": function(){ that.scrolling = true; },
            "mouseup.slider": function(){ that.scrolling = false; }
        };

        $(window).on(handler);
        $(".btn").on("click.slider", jQuery.proxy(this.btnhandler,this))
    },

    catchSlides: function(){
        // count slides and save selectors
        var array = [];

        for(var i=0; i<this.$elem.length; i++){    

            var el = this.$elem.eq(i);
            array[i] = el;
        }

        this.elements = array;
        this.slideCount = this.elements.length;
    },

    getPositions: function(){
        // what are the postions of those slides?
        var array = [];

        for(var i=0; i<this.slideCount; i++){ 

            var el = this.elements[i];
            array[i] = el[0].offsetTop;
        }

        this.posArray = array;
    },

    arrows: function(){
        if(this.slideCount>1){
            switch(this.lastSlide) {

                case 0: // erster slide
                    if(this.arrowUp.is(":visible")) this.arrowUp.hide();
                    if(!this.arrowDown.is(":visible")) this.arrowDown.show(); 
                break;

                case this.slideCount-1: // letzter slide
                    if(this.arrowDown.is(":visible")) this.arrowDown.hide();
                    if(!this.arrowUp.is(":visible")) this.arrowUp.show(); 
                break;

                default: 
                    this.arrowUp.show();
                    this.arrowDown.show();

            }
        }
        else {
            this.arrowUp.hide();
            this.arrowDown.hide();
        }
    },

    getY: function(){
        return window.pageYOffset;
    },

    newPos: function(jump){
        // go to the new coordinate, hide one of those arrows 
        // if first or last slide
        this.arrows();
        this.getPositions();
        this.jumpTo(jump);
    },

    clear: function(){
        this.lastY = this.getY();
        this.scrolling = false;
    },

    onResize: function(){
        if(!this.scrolling){
            rAF(jQuery.proxy(this.newPos,this));
        }
        this.scrolling = true;
    },

    onScroll: function(){
        if(!this.scrolling){
            rAF(jQuery.proxy(this.update,this));
        }
        this.scrolling = true;
    },

    update: function(){
        // which direction did the user scroll?
        if(this.lastY<this.getY()){ // down?
            this.slide("down");
        }
        else if(this.lastY>this.getY()){ // or up?
            this.slide("up");
        }
        else this.clear();
    },

    slide: function(string){
        if(string==="down" && this.lastSlide<this.slideCount-1){
            this.lastSlide++;
            this.newPos();
        }
        else if(string==="up" && this.lastSlide>0){
            this.lastSlide--;
            this.newPos();
        }
        else this.clear();
    },

    jumpTo: function(jump, slideIndex){
        var that = this,
            slideIndex = slideIndex || this.lastSlide,
            destination = this.posArray[slideIndex];

        this.scrolling = true;

        if(jump && jump!==undefined){
            // jump to position without animation
            $("html,body").stop().animate({scrollTop: destination}, 0, function(){ that.clear(); });
        }
        else $("html,body").stop().animate({scrollTop: destination}, this.scrollSpeed, function(){ that.clear(); });
    },

    keyhandler: function(e){
        switch(e.which) {
            case 38: 
            e.preventDefault();
            this.slide("up");// up
            break;

            case 40: 
            e.preventDefault();
            this.slide("down");// down
            break;

            default: return;
        }
    },

    btnhandler: function(e){
        // register arrow-buttons from ui
        var $next = $(".btn-next"),
            $prev = $(".btn-previous");

        e.preventDefault();

        if(e.target===$next || $.contains($next[0], e.target)) this.slide("down");
        else if(e.target===$prev || $.contains($prev[0], e.target)) this.slide("up");
    }
};

Slides.init();

希望有人可以提供帮助。谢谢。

4

0 回答 0