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