[转帖]Mootools源码分析-37 -- Fx.Scroll
原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-408229
原作者:我佛山人
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//平滑的滚动效果,演示:http://demos.mootools.net/Fx.Scroll
Fx.Scroll = new Class({
//继承自Fx类
Extends: Fx,
options: {
//滚动时的偏移坐标量
offset: {'x': 0, 'y': 0},
//滚轮时是否自动停止滚动效果
wheelStops: true
},
initialize: function(element, options) {
//作用的对象
this.element = this.subject = $(element);
//调用父类同名方法
arguments.callee.parent(options);
//为滚轮事件提供取消滚动的对象绑定,写在下面wheelStops的判断里应该会更好
var cancel = this.cancel.bind(this, false);
//如果提供作用对象有误,换成当前文档的body节点对象
if ($type(this.element) != 'element') this.element = $(this.element.getDocument().body);
var stopper = this.element;
//如果设置滚轮停止
if (this.options.wheelStops) {
//在滚动开始前添加滚轮事件监听
this.addEvent('onStart', function() {
stopper.addEvent('mousewheel', cancel);
}, true);
//在滚动结束后移除滚轮事件监听
this.addEvent('onComplete', function() {
stopper.removeEvent('mousewheel', cancel);
}, true);
}
},
//设置目标值
set: function() {
//给参数对象降维
var now = Array.flatten(arguments);
//滚动到指定坐标
this.element.scrollTo(now[0], now[1]);
},
//根据初始值,结束值和变量求目标值
compute: function(from, to, delta) {
var now = [];
//Ruby风格的两次循环,转为from和to是长度为2的数组
(2).times(function(i) {
now.push(Fx.compute(from[i], to[i], delta));
});
return now;
},
//开始滚动
start: function(x, y) {
//检查约束设置
if (!this.check(x, y)) return this;
//获取对象尺寸和滚动尺寸
var ōffsetSize = this.element.getSize(), scrollSize = this.element.getScrollSize();
//获取当前滚动位置
var scroll = this.element.getScroll(), values = {x: x, y: y};
for (var z in values) {
//计算当前坐标方向上的可滚动的最大值
var max = scrollSize[z] - offsetSize[z];
//如果提供滚动的目标值,保证目标值在有效范围内
if ($chk(values[z])) values[z] = ($type(valus[z]) == 'number') ? values[z].limit(0, max) : max;
//否则直接使用当前滚动位置值
else values[z] = scroll[z];
//加上配置的偏移量
values[z] += this.options.offset[z];
}
//调用父类Fx的同名方法
return arguments.callee.parent([scroll.x, scroll.y], [values.x, values.y]);
},
//滚动到顶部,x轴滚动位置不变
toTop: function() {
return this.start(false, 0);
},
//滚动到左边,y轴滚动位置不变
toLeft: function() {
return this.start(0, false);
},
//滚动到右边,y轴滚动位置不变
toRight: function() {
return this.start('right', false);
},
//滚动到底部,x轴滚动位置不变
toBottom: function() {
return this.start(false, 'bottom');
},
//滚动到指定Element的绝对坐标位置
toElement: function(el) {
//获取el的绝对坐标值
var position = $(el).getPosition(this.element);
//开始滚动
return this.start(position.x, position.y);
}
});
Fx.Scroll = new Class({
//继承自Fx类
Extends: Fx,
options: {
//滚动时的偏移坐标量
offset: {'x': 0, 'y': 0},
//滚轮时是否自动停止滚动效果
wheelStops: true
},
initialize: function(element, options) {
//作用的对象
this.element = this.subject = $(element);
//调用父类同名方法
arguments.callee.parent(options);
//为滚轮事件提供取消滚动的对象绑定,写在下面wheelStops的判断里应该会更好
var cancel = this.cancel.bind(this, false);
//如果提供作用对象有误,换成当前文档的body节点对象
if ($type(this.element) != 'element') this.element = $(this.element.getDocument().body);
var stopper = this.element;
//如果设置滚轮停止
if (this.options.wheelStops) {
//在滚动开始前添加滚轮事件监听
this.addEvent('onStart', function() {
stopper.addEvent('mousewheel', cancel);
}, true);
//在滚动结束后移除滚轮事件监听
this.addEvent('onComplete', function() {
stopper.removeEvent('mousewheel', cancel);
}, true);
}
},
//设置目标值
set: function() {
//给参数对象降维
var now = Array.flatten(arguments);
//滚动到指定坐标
this.element.scrollTo(now[0], now[1]);
},
//根据初始值,结束值和变量求目标值
compute: function(from, to, delta) {
var now = [];
//Ruby风格的两次循环,转为from和to是长度为2的数组
(2).times(function(i) {
now.push(Fx.compute(from[i], to[i], delta));
});
return now;
},
//开始滚动
start: function(x, y) {
//检查约束设置
if (!this.check(x, y)) return this;
//获取对象尺寸和滚动尺寸
var ōffsetSize = this.element.getSize(), scrollSize = this.element.getScrollSize();
//获取当前滚动位置
var scroll = this.element.getScroll(), values = {x: x, y: y};
for (var z in values) {
//计算当前坐标方向上的可滚动的最大值
var max = scrollSize[z] - offsetSize[z];
//如果提供滚动的目标值,保证目标值在有效范围内
if ($chk(values[z])) values[z] = ($type(valus[z]) == 'number') ? values[z].limit(0, max) : max;
//否则直接使用当前滚动位置值
else values[z] = scroll[z];
//加上配置的偏移量
values[z] += this.options.offset[z];
}
//调用父类Fx的同名方法
return arguments.callee.parent([scroll.x, scroll.y], [values.x, values.y]);
},
//滚动到顶部,x轴滚动位置不变
toTop: function() {
return this.start(false, 0);
},
//滚动到左边,y轴滚动位置不变
toLeft: function() {
return this.start(0, false);
},
//滚动到右边,y轴滚动位置不变
toRight: function() {
return this.start('right', false);
},
//滚动到底部,x轴滚动位置不变
toBottom: function() {
return this.start(false, 'bottom');
},
//滚动到指定Element的绝对坐标位置
toElement: function(el) {
//获取el的绝对坐标值
var position = $(el).getPosition(this.element);
//开始滚动
return this.start(position.x, position.y);
}
});