您的位置:首页 > Web前端 > JQuery

jQuery插件开发之windowScroll

2015-07-13 20:12 891 查看
回首望,曾经洋洋得意的代码现在不忍直视。曾经看起来碉堡的效果现在也能稍微弄点出来。社会在往前发展,人也得向前迈进。

参考于搜狗浏览器4.2版本首页的上下滚动效果。主要实现整个窗口的上下和左右滚动逻辑,还有很多可以拓展的空间。希望大家能多提意见与建议。

  欢迎fork项目:https://github.com/codetker/myWindowScroll, 实现的效果见http://www.梦萦无双.xyz/myWindowScroll/demo/Default.html, 应用见http://wechat.wutnews.net/Web/PhotoWall/(尚在改善中)。

插件效果:
实现window的上下滚动,默认绑定键盘上下按钮和鼠标滑轮
实现window的左右滚动,默认绑定键盘左右按钮
可附加ul li协助控制滚动
可修改后附加缓动函数,实现多种效果,详情见缓动函数表 http://easings.net/zh-cn#easeInOutQuad
html 结构(ZenCoding形式)

-div.divClass
-div.toLeftOrTop
-div.toRightOrBottom
-div.stageClass*n

-ul.controlUl
-li.liClass*n


其中div.toLeftOrTop,div.toRightOrBottom,ul.controlUl可选

调用方法(详情见demo)(按需设置参数)
A.vertical

$(".divClass").windowScroll({
'choose': 0,             //垂直滚动,默认
'verticalSpeed': 1,      //控制垂直滚动速度
'objControlUl': 'ul.controlUl', //控制垂直滚动按钮,默认为null
'list': '.stageClass',          //垂直滚动的对象
'crash': true,                  //撞击底部特效
'toTop': '.toLeftOrTop',        //向上按钮,默认为null
'toBottom': 'toRightOrBottom',  //向下按钮,默认为null
'liHover': 'stageSelect'        //设置当前stage的类名
});


B.horizontal

$(".divClass").windowScroll({
'choose': 1,               //水平滚动
'horizontalSpeed': 1,      //控制水平滚动速度
'objControlUl': 'ul.controlUl', //控制水平滚动按钮,默认为null
'list': '.stageClass',          //水平滚动的对象
'crash': true,                  //撞击左右特效
'toTop': '.toLeftOrTop',        //向左按钮,默认为null
'toBottom': 'toRightOrBottom',  //向右按钮,默认为null
'liHover': 'stageSelect'        //设置当前page的类名
});


运行demo
最简单的方法为改Default.html中jquery对应script元素的src为本地的jquery(离线)或CDN中的jquery(在线),然后双击Default.html即可
或者配置myBoxScroll.jquery.json or package.json

PS:代码之间耦合过强,可重复利用的很多,准备参考学长的建议按模块写个人函数库,通过模块加载注入需要使用的工具函数

Demo代码如下:

HTML

/*
* windowScroll 0.1
* window滚动插件,上下左右,可选择是否回弹。参考搜狗欢迎页面
* 兼容等常见浏览器
* 借鉴搜狗4.2版http://ie.sogou.com/features4.2.html
*/
;(function($, window, document, undefined) {
//定义构造函数
var WindowObj = function(ele, opt) {
this.$element = ele;
this.defaults = {
'choose': 0,
'list': null,
'verticalSpeed': 1,
'horizontalSpeed': 1,
'objControlUl': null,
'toLeft': null,
'toRight': null,
'toTop': null,
'toBottom': null,
'crash': true,
'liHover': null
};

this.options = $.extend({}, this.defaults, opt);

};

//给构造函数添加方法
WindowObj.prototype = {

//上下滚动的方法
verticalMove: function() {
var
obj = this.$element,
speed = this.options.verticalSpeed,
objControl = this.options.objControlUl,
controlList = $(objControl).find('li'),
windowHeight = $(window).height(),
list = this.options.list,
listMax = $(list).length,
toTop = this.options.toTop,
toBottom = this.options.toBottom,
crashButton = this.options.crash,
liHover = this.options.liHover,
stop = 0,
stageIndex,
windowobject = is_chrome();

function setCss() {
$(obj).css({
'width': $(window).width() + 'px',
'height': $(window).height() * listMax + 'px'
});
$(list).css({
'min-width': $(window).width() + 'px',
'height': $(window).height() + 'px'
});
}
setCss();

function markStage() {
getIndex();
$(controlList).removeClass(liHover);
$(controlList).eq(stageIndex).addClass(liHover);
}

function is_chrome() {
var is_ch = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (is_ch) {
//判断webkit内核,供scrollTop兼容性使用
return 'body';
} else {
//支持IE和FF
return 'html';
}
}

//阻止默认行为和冒泡
function stopDefaultAndBubble(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;

if (e.stopPropagation) {
e.stopPropagation();
}
e.cancelBubble = true;
}

//得到当前的垂直位置
function getIndex() {
stageIndex = Math.round($(window).scrollTop() / windowHeight);
}

function goTop() {
getIndex();
scrollStage(windowobject, stageIndex, 1);
}

function goBottom() {
getIndex();
scrollStage(windowobject, stageIndex, -1);
}

//绑定键盘上下按键事件
$(document).keydown(function(event) {
/* 绑定keycode38,即向上按钮 */
if (event.keyCode == 38) {
goTop();

} else if (event.keyCode == 40) { //绑定40,即向下按钮
goBottom();
}
});

//绑定滑轮功能的函数
function handle(delta) {
getIndex();
if (delta < 0) {
scrollStage(windowobject, stageIndex, -1); //stageIndex为当前页码
} else {
scrollStage(windowobject, stageIndex, 1); //stageIndex为当前页码
}

}

//判断滑轮,解决兼容性
function wheel(event) {
var delta = 0;
if (!event) event = window.event;
if (event.wheelDelta) {
delta = event.wheelDelta;
if (window.opera) delta = -delta;
} else if (event.detail) {
delta = -event.detail;
}
if (delta)
handle(delta); //调用执行函数
}

//注册事件
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll', wheel, false);
}
window.onmousewheel = document.onmousewheel = wheel;

//绑定鼠标滚轮事件
$(document).bind('mousedown', function(e) {
if (e.which == 2) { //which=2代表鼠标滚轮,即为中键
stopDefaultAndBubble(e);

//bugfix 搜狗浏览器的ie内核只有在定时器触发这个函数才生效
setTimeout(function() {
stopDefaultAndBubble(e);
}, 10);
}
});

//如果有ul li控制按钮
if (objControl !== null) {
$(objControl).delegate('li', 'click', function() {
stageIndex = $(this).index();
scrollStage(windowobject, stageIndex, 0);
});
}

//如果有上下控制
$(toTop).click(function() {
goTop();
});
$(toBottom).click(function() {
goBottom();
});

function scrollStage(obj, stIndex, dir) {

var
sIndex = stIndex,
windowobject = obj,
direction = 0 || dir,
target = windowHeight * sIndex;

function move() {
$(windowobject).animate({
'scrollTop': target + 'px'
}, 1000 * speed, function() {
crash(1, target, 20, 150, -1);

markStage();
});
}

function after_crash(distant, time, termin) {
if (distant <= 15 || time > 150) {
stop = 1; //停止碰撞
$(windowobject).animate({
'scrollTop': termin + 'px'
}, time, function() {
stop = 0;
});
}
}

//撞击函数
function crash(direction, termin, distant, time, aspect) {
if (crashButton) {
if (!stop) {
if (direction === 1) {
direction = 0;
if (aspect === 1) {
$(windowobject).animate({
'scrollTop': '-=' + distant + 'px'
}, time, function() {
crash(direction, termin, distant * 0.6, time, 1);
after_crash(distant, time, termin);
});
} else {
$(windowobject).animate({
'scrollTop': '+=' + distant + 'px'
}, time, function() {
crash(direction, termin, distant * 0.6, time, -1);
after_crash(distant, time, termin);
});
}

} else if (direction === 0) {
direction = 1;
if (aspect === 1) {
$(windowobject).animate({
'scrollTop': termin + 'px'
}, time, function() {
crash(direction, termin, distant * 0.6, time, 1);
after_crash(distant, time, termin);
});
} else {
$(windowobject).animate({
'scrollTop': termin + 'px'
}, time, function() {
crash(direction, termin, distant * 0.6, time, -1);
after_crash(distant, time, termin);
});
}

}
}
}

}

if (!$(windowobject).is(':animated')) {

switch (direction) {
case 0:
if ($(window).scrollTop() > target) {
direction = -1;
move();
} else if ($(window).scrollTop() == windowHeight * sIndex) {
direction = 0;
crash(1, target, 20, 150, -1);
} else {
direction = 1;
move();
}
break;

case 1:
if (sIndex === 0) {
crash(1, target, 20, 150, 1);
} else {
sIndex -= 1;
target = windowHeight * sIndex;
move();
}
break;

case -1:
if (sIndex === listMax - 1) {
crash(1, target, 20, 150, -1);
} else {
sIndex += 1;
target = windowHeight * sIndex;
move();
}
break;

default:
}
}
}

},

//左右滚动
horizontalMove: function() {
var
obj = this.$element,
speed = this.options.horizontalSpeed,
objControl = this.options.objControlUl,
controlList = $(objControl).find('li'),
windowWidth = $(window).width(),
list = this.options.list,
listMax = $(list).length,
liHover = this.options.liHover,
toLeft = this.options.toLeft,
toRight = this.options.toRight,
crashButton = this.options.crash,
pageIndex;

function setCss() {
$(obj).css({
'width': windowWidth * listMax + 'px',
'height': $(window).height() + 'px'
});
$(list).css({
'width': windowWidth + 'px',
'min-height': $(window).height() + 'px'
});
}
setCss();

function markPage() {
getPageIndex();
$(controlList).removeClass(liHover);
$(controlList).eq(pageIndex).addClass(liHover);
}

function getPageIndex() {
pageIndex = (-1) * Math.round(parseInt($(obj).css('margin-left')) / windowWidth);
}

function goLeft() {
getPageIndex();
scrollPage(obj, pageIndex, 1);
}

function goRight() {
getPageIndex();
scrollPage(obj, pageIndex, -1);
}

//绑定键盘左右按键事件
$(document).keydown(function(event) {
//判断event.keyCode为39(即向右按钮)
if (event.keyCode === 39) {
goRight();
}
//判断event.keyCode为37(即向左按钮
else if (event.keyCode === 37) {
goLeft();
}
});

//如果有ul li控制按钮
if (objControl !== null) {
$(objControl).delegate('li', 'click', function() {
pageIndex = $(this).index();
scrollPage(obj, pageIndex, 0);
});
}

//如有有左右控制按钮
$(toLeft).click(function() {
goLeft();
});
$(toRight).click(function() {
goRight();
});

function scrollPage(obj, pageIndex, dir) {
var
windowobject = obj,
direction = 0 || dir,
dist = Math.round(parseInt($(obj).css('margin-left'))),
aim;

function getAim() {
aim = pageIndex * windowWidth * (-1);
}

function crash(type) {
if (crashButton) {
if (type === 'left') {
$(windowobject).animate({
'margin-left': '+=' + '50px'
}, 500).animate({
'margin-left': '-=' + '100px'
}, 500).animate({
'margin-left': '+=' + '50px'
}, 500);
} else {
$(windowobject).animate({
'margin-left': '-=' + '50px'
}, 500).animate({
'margin-left': '+=' + '100px'
}, 500).animate({
'margin-left': '-=' + '50px'
}, 500);
}
}

}

function move() {
$(windowobject).animate({
'margin-left': aim + 'px'
},
1000 * speed,
function() {
markPage();
});
}

if (!$(windowobject).is(':animated')) {
switch (direction) {

case 0:
getAim();
if (dist !== aim) {
move();
} else {
direction = 0;
crash('left');
}
break;

case 1:
if (pageIndex === 0) {
crash('left');
} else {
pageIndex -= 1;
getAim();
move();
}
break;

case -1:
if (pageIndex === (listMax - 1)) {
crash('right');
} else {
pageIndex += 1;
getAim();
move();
}
break;

default:
break;
}

}
}

}
};

//绑定方法到jquery对象原型上
$.fn.windowScroll = function(options) {

var windowObj = new WindowObj(this, options);

if (windowObj.options.choose === 0) {
return windowObj.verticalMove();
} else if (windowObj.options.choose === 1) {
return windowObj.horizontalMove();
} else {
//add some functions
}
};
})(jQuery, window, document);


View Code JS
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: