/**
* 元素固定插件 by sunhaochen
* create time 2017-11-1 16:39:40
* **********参数说明***********
* topSpace 固定元素上面的间距,譬如前面已经有一个固定元素了,此时就不能覆盖到前面的固定元素,把这个值设置为前面元素的高度就可以了
* bottomLimit 向下滚动时,当下面有不能覆盖的元素时,就把固定元素固定在这里,不再随滚动条固定,以不覆盖下面的元素,譬如站点的脚部模块
* topSpace bottomLimit 参数属性的有效值为像素值、数值、html元素、jQuery包装的html元素
* topSpace 为元素时取该元素的高度
* bottomLimit 为元素时取该元素的距html文档顶端高度
* ******回调函数*******
* stickBefore 固定前回调
* stickAfter 固定后回调
* unStickBefore 解除固定前回调
* unStickAfter 解除固定后回调
* **********参数说明***********
* @param {[object]} args [配置参数]
* @return {[object]} [jQ对象]
*/
$.fn.stickUp = function(args){
var w = window;
var w_w = $(w).width();
var w_h = $(w).height();
var p_h = $('body,html').height();
var options = $.extend({
topSpace : 0,
bottomLimit : p_h,
stickBefore : $.noop,
stickAfter : $.noop,
unStickBefore : $.noop,
unStickAfter : $.noop
},args||{});
lastScrolDirction = 0;
var paramIsErro = false;
for ( var k in options ){
if ( $.inArray(k,['topSpace','bottomLimit']) ){
if ( typeof options[k] === 'string' ) {
options[k] = parseFloat(options[k]);
if ( isNaN(options[k]) ){
paramIsErro = true;
}
} else if ( !options[k] ) {
paramIsErro = true;
} else if ( typeof options[k] === 'object' ) {
if ( (options[k].length && !options[k][0].tagName) || (!options[k].length && !options[k].tagName) ) {
paramIsErro = true;
} else {
if ( options[k][0].tagName ){
if ( k === 'topSpace' ){
options[k] = options[k].outerHeight();
} else if ( k === 'bottomLimit' ) {
options[k] = options[k].offset().top;
}
}
}
}
}
}
if ( paramIsErro ){
console.error('topSpace、bottomLimit参数属性的有效值为像素值、数值、html元素、jQuery包装的html元素');
}
options.topSpace = parseFloat(options.topSpace);
options.bottomLimit = parseFloat(options.bottomLimit);
var task = [];
this.each(function(){
var that = this;
var $t = $(that);
var e_w = $t.outerWidth();
var e_h = $t.outerHeight();
that.originPosi = {
position: $t.css('position'),
top: $t.css('top'),
right: $t.css('right'),
bottom: $t.css('bottom'),
left: $t.css('left'),
margin: $t.css('margin'),
cssFloat: $t.css('cssFloat')
}
// 占位空容器
var $emptyPlace = $('<div>').insertBefore(that).css($.extend({width:e_w,height:e_h,display:'none'},that.originPosi));
var e_p = $t.offset();
task.push(function(dir){
var w_t = $(w).scrollTop();
var e_t = $(that).offset().top;
var topSpace = options.topSpace;
// 限定顶部到下端区域
var conda = w_t + topSpace + e_h < options.bottomLimit;
var condb = w_t + topSpace > e_p.top;
if ( dir === 'up' ){
var condc = true;
} else {
var condc = w_t >= e_t - topSpace;
}
$emptyPlace.show();
// console.log(conda , condb , condc)
if ( conda && condb && condc ) {
options.stickBefore.call({node: that,place: $emptyPlace});
$t.css({
position: 'fixed',
margin: 0,
top: topSpace,
left: e_p.left
});
options.stickAfter.call({node: that,place: $emptyPlace});
} else if ( options.bottomLimit && e_t > e_p.top && w_t + w_h > options.bottomLimit ) {
options.stickBefore.call({node: that,place: $emptyPlace});
// 减去元素用于定位的父节点到达文档顶部的高度,因为absolute是相对于含有定位属性的父节点来定位的
var e_offset_parent = _offset_parent($t,{top:0,left:0});
// 到达下端限定不容许覆盖元素
$t.css({
position: 'absolute',
margin: 0,
top: options.bottomLimit - e_h - e_offset_parent.top,
left: e_p.left - e_offset_parent.left
});
options.stickAfter.call({node: that,place: $emptyPlace});
} else {
options.unStickBefore.call({node: that,place: $emptyPlace});
$(that).css(that.originPosi);
$emptyPlace.hide();
options.unStickAfter.call({node: that,place: $emptyPlace});
}
})
});
function _offset_parent($t,n){
var $p = $t.offsetParent();
if ( $p.is('body') ) {
return n;
} else {
return _offset_parent($p,{
top : $p.offset().top + n.top,
left : $p.offset().left + n.left
});
}
}
$(w).scroll(function(){
var win_top = $(w).scrollTop();
var dir = lastScrolDirction > win_top ? 'up' : 'down';
lastScrolDirction = win_top
for ( var i = 0; i < task.length; i++ ) {
task[i](dir);
}
}).scroll();
}
元素固定插件
最新推荐文章于 2022-08-04 20:44:29 发布