個人のホームページ用のプラグインを作成しました。このプラグインは、一連の要素をスクロールして、各要素の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();
誰かが助けてくれることを願っています。ありがとう。