288 lines
9.7 KiB
JavaScript
288 lines
9.7 KiB
JavaScript
/**
|
|
* amWiki Web端 - 滚动条模块
|
|
* @author Tevin
|
|
*/
|
|
|
|
;
|
|
(function (win, $) {
|
|
|
|
'use strict';
|
|
|
|
//定时检测内容高度作为补充
|
|
var list = [];
|
|
setInterval(function () {
|
|
for (var i = 0, item; item = list[i]; i++) {
|
|
item.checkHeightWidth();
|
|
}
|
|
}, 500);
|
|
|
|
/**
|
|
* 页面滚动
|
|
* @param {Element} _this
|
|
* @constructor
|
|
*/
|
|
var Scroller = function (_this) {
|
|
this.$e = {
|
|
container: $(_this), //主容器
|
|
inner: null, //正文内容
|
|
barY: null, //垂直滚动条外层
|
|
boxY: null, //垂直滚动条
|
|
sliderY: null, //垂直滑块
|
|
barX: null, //水平滚动条外层
|
|
boxX: null, //水平滚动条
|
|
sliderX: null //水平滑块
|
|
};
|
|
this._data = {
|
|
xRolling: this.$e.container.attr('data-x-rolling') == 'true',
|
|
maxTop: 0, //最大top值
|
|
barH: 0, //滚动条高度
|
|
sliderH: 0, //滑块高度
|
|
contentH: 0, //内容高度
|
|
containerH: 0, //容器高度
|
|
contentHLast: 0, //上次内容高度
|
|
barW: 0, //滚动条宽度
|
|
sliderW: 0, //滑块宽度
|
|
contentW: 0, //内容宽度
|
|
containerW: 0, //容器宽度
|
|
contentWLast: 0 //上次内容宽度
|
|
};
|
|
this._init();
|
|
};
|
|
|
|
/**
|
|
* 初始化
|
|
* @private
|
|
*/
|
|
Scroller.prototype._init = function () {
|
|
var that = this;
|
|
var barHtml = '<div class="scrollbar scrollbar-y" onselectstart="return false"><div><i></i></div></div>';
|
|
barHtml += this._data.xRolling ?
|
|
'<div class="scrollbar scrollbar-x" onselectstart="return false"><div><i></i></div></div>' : '';
|
|
this.$e.container.append(barHtml);
|
|
//获取元素
|
|
this.$e.barY = this.$e.container.find('.scrollbar-y');
|
|
this.$e.boxY = this.$e.barY.children('div');
|
|
this.$e.sliderY = this.$e.barY.find('i');
|
|
if (this._data.xRolling) {
|
|
this.$e.barX = this.$e.container.find('.scrollbar-x');
|
|
this.$e.boxX = this.$e.barX.children('div');
|
|
this.$e.sliderX = this.$e.barX.find('i');
|
|
}
|
|
this.$e.inner = this.$e.container.children('.scroller-inner');
|
|
//绑定事件
|
|
this._onWinResize();
|
|
$(win).on('resize', function () {
|
|
that._onWinResize();
|
|
that.checkHeightWidth();
|
|
});
|
|
this.$e.container.on('scrollbar', function () {
|
|
that.checkHeightWidth();
|
|
});
|
|
this.$e.inner.on({
|
|
'click': function () {
|
|
that.checkHeightWidth();
|
|
},
|
|
'scroll': function () {
|
|
that._reScroll();
|
|
}
|
|
});
|
|
this.checkHeightWidth();
|
|
this._bindAction();
|
|
};
|
|
|
|
/**
|
|
* 滑块操作
|
|
* @private
|
|
*/
|
|
Scroller.prototype._bindAction = function () {
|
|
var that = this;
|
|
var onDrag = false;
|
|
var _y = 0,
|
|
top = 0,
|
|
_x = 0,
|
|
left = 0;
|
|
this.$e.body = $('body');
|
|
this.$e.boxY.on({
|
|
'mousedown': function (e) {
|
|
onDrag = 'y';
|
|
that.$e.body.attr('onselectstart', 'return false');
|
|
that.$e.barY.addClass('active');
|
|
_y = e.pageY;
|
|
top = parseFloat(that.$e.sliderY.css('top'));
|
|
if (that.$e.barY.parents('#main').length > 0) {
|
|
that.$e.body.children('aside').hide();
|
|
}
|
|
}
|
|
});
|
|
if (this._data.xRolling) {
|
|
this.$e.boxX.on({
|
|
'mousedown': function (e) {
|
|
onDrag = 'x';
|
|
that.$e.body.attr('onselectstart', 'return false');
|
|
that.$e.barX.addClass('active');
|
|
_x = e.pageX;
|
|
left = parseFloat(that.$e.sliderX.css('left'));
|
|
}
|
|
});
|
|
}
|
|
$(win.document).on({
|
|
'mousemove': function (e) {
|
|
if (onDrag == 'y') {
|
|
that.scrollYTo(top + e.pageY - _y);
|
|
} else if (onDrag == 'x') {
|
|
that.scrollXTo(left + e.pageX - _x);
|
|
}
|
|
},
|
|
'mouseup': function () {
|
|
that.$e.body.removeAttr('onselectstart', 'return false')
|
|
.children('aside').show();
|
|
if (onDrag == 'y') {
|
|
that.$e.barY.removeClass('active');
|
|
} else if (onDrag == 'x') {
|
|
that.$e.barX.removeClass('active');
|
|
}
|
|
onDrag = false;
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 尺寸缩放
|
|
* @private
|
|
*/
|
|
Scroller.prototype._onWinResize = function () {
|
|
if (isMobi()) {
|
|
this.$e.inner.removeAttr('style').removeClass('on');
|
|
} else {
|
|
this.$e.inner.css({
|
|
width: this.$e.container.width() + 30,
|
|
paddingRight: 13,
|
|
paddingBottom: 16
|
|
}).addClass('on');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 重设滑块大小
|
|
* @private
|
|
*/
|
|
Scroller.prototype._resize = function () {
|
|
var that = this;
|
|
this._data.containerH = this.$e.inner.height();
|
|
//当内容高度小于等于容器时,不显示滚动条
|
|
if (this._data.contentH <= this._data.containerH) {
|
|
this._data.contentH = this._data.containerH;
|
|
this.$e.barY.addClass('off');
|
|
} else {
|
|
this.$e.barY.removeClass('off');
|
|
}
|
|
//设置滑块大小
|
|
this._data.barH = this.$e.boxY.height();
|
|
this._data.sliderH = this._data.containerH / that._data.contentH * this._data.barH;
|
|
this.$e.sliderY.height(this._data.sliderH);
|
|
//计算最大高度
|
|
this._data.maxTop = (this._data.barH - this._data.sliderH) / this._data.barH * this._data.contentH + 1;
|
|
//水平方向
|
|
if (this._data.xRolling) {
|
|
this._data.containerW = this.$e.inner.width();
|
|
//当内容宽度不超过容器时,不显示滚动条
|
|
if (this._data.contentW <= this._data.containerW) {
|
|
this._data.contentW = this._data.containerW;
|
|
this.$e.barX.addClass('off');
|
|
} else {
|
|
this.$e.barX.removeClass('off');
|
|
}
|
|
//设置滑块大小
|
|
this._data.barW = this.$e.boxX.width();
|
|
this._data.sliderW = this._data.containerW / that._data.contentW * this._data.barW;
|
|
this.$e.sliderX.width(this._data.sliderW);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 重设滑块顶部距离
|
|
* @private
|
|
*/
|
|
Scroller.prototype._reScroll = function () {
|
|
var that = this;
|
|
var top1 = this.$e.inner.scrollTop();
|
|
var barTop = top1 / this._data.contentH * this._data.barH;
|
|
//限制滑动边界 (由事件触发的滚动不会向上过界)
|
|
if (barTop + this._data.sliderH >= this._data.barH) {
|
|
barTop = this._data.barH - this._data.sliderH;
|
|
this.$e.sliderY.css('top', barTop);
|
|
this.$e.inner.scrollTop(this._data.maxTop);
|
|
} else {
|
|
this.$e.sliderY.css('top', barTop);
|
|
}
|
|
//水平方向
|
|
if (this._data.xRolling) {
|
|
var barLeft = this.$e.inner.scrollLeft() / this._data.contentW * this._data.barW;
|
|
//水平方向没有鼠标滚动事件
|
|
this.$e.sliderX.css('left', barLeft);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 垂直滚动到某位置
|
|
* @param {Number} num
|
|
* @public
|
|
*/
|
|
Scroller.prototype.scrollYTo = function (num) {
|
|
var barTop = num;
|
|
barTop = barTop < 0 ? 0 : barTop;
|
|
barTop = barTop + this._data.sliderH > this._data.barH ? this._data.barH - this._data.sliderH : barTop;
|
|
this.$e.sliderY.css('top', barTop);
|
|
this.$e.inner.scrollTop(barTop / this._data.barH * this._data.contentH);
|
|
};
|
|
|
|
/**
|
|
* 水平滚动到某位置
|
|
* @param {Number} num
|
|
* @public
|
|
*/
|
|
Scroller.prototype.scrollXTo = function (num) {
|
|
var barLeft = num;
|
|
barLeft = barLeft < 0 ? 0 : barLeft;
|
|
barLeft = barLeft + this._data.sliderW > this._data.barW ? this._data.barW - this._data.sliderW : barLeft;
|
|
this.$e.sliderX.css('left', barLeft);
|
|
this.$e.inner.scrollLeft(barLeft / this._data.barW * this._data.contentW);
|
|
};
|
|
|
|
/**
|
|
* 检查高度宽度
|
|
* @public
|
|
*/
|
|
Scroller.prototype.checkHeightWidth = function () {
|
|
var that = this;
|
|
this._data.contentH = 0;
|
|
this._data.contentW = 0;
|
|
this.$e.inner.children('.scroller-content').each(function () {
|
|
that._data.contentH += $(this).outerHeight();
|
|
that._data.contentW += $(this).outerWidth();
|
|
});
|
|
//修正 webkit 中滚动条本身占位
|
|
if (/webkit/.test(navigator.userAgent.toLowerCase())) {
|
|
that._data.contentH += 15;
|
|
}
|
|
//如果高度未改变不进行操作
|
|
if (this._data.contentH == this._data.contentHLast && this._data.contentW == this._data.contentWLast) {
|
|
return;
|
|
} else {
|
|
this._data.contentHLast = this._data.contentH;
|
|
this._data.contentWLast = this._data.contentW;
|
|
}
|
|
this._resize();
|
|
this._reScroll();
|
|
};
|
|
|
|
//注册到 jQuery
|
|
$.extend($.fn, {
|
|
scrollbar: function () {
|
|
return this.each(function () {
|
|
list.push(new Scroller(this));
|
|
});
|
|
}
|
|
});
|
|
|
|
})(window, jQuery); |