我为我的个人主页编写了一个插件,它应该滚动浏览一系列元素,捕捉到每个元素 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();
希望有人可以提供帮助。谢谢。