原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-410192
原作者:我佛山人
代码
//
滑动条
// 演示:http://demos.mootools.net/Slider
var Slider = new Class({
// 继承实现Events和Options,UI插件的特征
Implements: [Events, Options],
options: { /*
//位置改变事件
onChange: $empty,
//拖动改变位置完成事件
onComplete: $empty, */
// 每一步的事件
onTick: function (position) {
// 如果指定吸附,根据步数计算位置
if ( this .options.snap) position = this .toPosition( this .step);
// 设置滑块的位置
this .knob.setStyle( this .property, position);
},
snap: false ,
// 偏移量
offset: 0 ,
// 指定滑动范围
range: false ,
// 滚轮支持
wheel: false ,
// 总步数
steps: 100 ,
// 滑动模式,水平或纵向
mode: ' horizontal '
},
// 构造函数,需要三个参数
// element为滑块所在容器,knob为滑块
initialize: function (element, knob, options) {
// 合并参数
this .setOptions(options);
// 取滑块所在的容器对象
this .element = $(element);
// 滑块
this .knob = $(knob);
// 初始化位置标记变量
this .previousChange = this .previousEnd = this .step = - 1 ;
// 添加鼠标按下的事件监听,实现点击时自动滑到指定位置
this .element.addEvent( ' mousedown ' , this .clickedElement.bind( this ));
// 如果设置支持滚轮,为容器添加滚轮监听事件
if ( this .options.wheel) this .element.addEvent( ' mousewheel ' , this .scrolledElement.bindWithEvent( this ));
// 初始化
var offset, limit = {}, modifiers = { ' x ' : false , ' y ' : false };
// 根据不同滑动模式初始化变量值
switch ( this .options.mode) {
// 纵向滑动时
case ' vertical ' :
// 别名为y轴方向
this .axis = ' y ' ;
// 这时主要是需要改变滑块CSS属性中的top
this .property = ' top ' ;
// 此时需要取值的属性为offsetHeiht
offset = ' offsetHeight ' ;
break ;
// 横向滑动时
case ' horizontal ' :
// 别名为x轴方向
this .axis = ' x ' ;
// 这时主要是需要改变滑块CSS属性中的left
this .property = ' left ' ;
// 此时需要取值的属性为offsetWidth
offset = ' offsetWidth ' ;
}
// 取滑块在当前滑动方向上的尺寸的一半
this .half = this .knob[offset] / 2 ;
// 计算滑块移动的总距离
this .full = this .element[offset] - this .knob[offset] + ( this .options.offset * 2 );
// 取范围的下限,默认为0
this .min = $chk( this .options.range[ 0 ]) ? this .options.range[ 0 ] : 0 ;
// 取范围的上限,默认为滑动的总步数
this .max = $chk( this .options.range[ 1 ]) ? this .options.range[ 1 ] : this .options.steps;
// 计算范围值
this .range = this .max - this .min;
// 总步数,如果steps参数值为0,则设为滑块移动的总距离
this .steps = this .options.steps || this .full;
// 计算每滑动一步的距离
this .stepSize = Math.abs( this .range) / this .steps;
// 计算每一步所占的宽度(根据上面的等级,这里不如直接用this.stepWidth = this.full/this.steps)
this .stepWidth = this .stepSize * this .full / Math.abs( this .range) ;
// 滑块相对于容器为相对定位
this .knob.setStyle( ' position ' , ' relative ' ).setStyle( this .property, - this .options.offset);
// 当前方向上对应的属性,转化用于Drag类的参数
modifiers[ this .axis] = this .property;
// 滑块的坐标范围
limit[ this .axis] = [ - this .options.offset, this .full - this .options.offset];
// 使滑块可拖动
this .drag = new Drag( this .knob, {
snap: 0 ,
// 滑块的可拖动范围
limit: limit,
// 指定拖动的方向及对应属性
modifiers: modifiers,
onDrag: this .draggedKnob.bind( this ),
onStart: this .draggedKnob.bind( this ),
onComplete: function () {
this .draggedKnob();
this .end();
}.bind( this )
});
// 如果指定吸附值
if ( this .options.snap) {
// 滑块拖动将网格化,单元格边长为滑动每一步所占的宽度
this .drag.options.grid = Math.ceil( this .stepWidth);
// 改变移动范围的上限,此时忽略偏移量
this .drag.options.limit[ this .axis][ 1 ] = this .full;
}
},
// 设置值
set: function (step) {
// 当范围上下限从小到大并且当前步值小于下限,或当范围上下限从大到小并且当前步值大于下限时,设置步值为下限值
if ( ! (( this .range > 0 ) ^ (step < this .min))) step = this .min;
// 当范围上下限从小到大并且当前步值大于是限,或当范围上下限从大到小并且当前步值小于上限时,设置步值为上限值
if ( ! (( this .range > 0 ) ^ (step > this .max))) step = this .max;
// 计算步数
this .step = Math.round(step);
// 检查步数变化,以决定是否触发事件
this .checkStep();
// 结束滑动
this .end();
// 触发步进事件
this .fireEvent( ' onTick ' , this .toPosition( this .step));
return this ;
},
// 点击直接跳到指定位置
clickedElement: function (event) {
// 判断方向
var dir = this .range < 0 ? - 1 : 1 ;
// 取当前模式下的鼠标在容器内的偏移值
var position = event.page[ this .axis] - this .element.getPosition()[ this .axis] - this .half;
// 边界处理
position = position.limit( - this .options.offset, this .full - this .options.offset);
// 计算步数
this .step = Math.round( this .min + dir * this .toStep(position));
// 检查步数变化,以决定是否触发事件
this .checkStep();
// 结束滑动
this .end();
// 触发步进事件
this .fireEvent( ' onTick ' , position);
},
// 利用滚轮跳到指定位置
scrolledElement: function (event) {
// 横向滑动和纵向滑动时,滚轮前滚和后滚导致的滑块的变化方向相反
var mode = ( this .options.mode == ' horizontal ' ) ? (event.wheel < 0 ) : (event.wheel > 0 );
// mode为真是向小值(左上)滑动,返之向大值(右下)滑动
this .set(mode ? this .step - this .stepSize : this .step + this .stepSize);
// 阻止事件冒泡及返回值
event.stop();
},
// 滑块移动时的处理
draggedKnob: function () {
// 判断方向
var dir = this .range < 0 ? - 1 : 1 ;
// 取当前模式下的鼠标坐标值
var position = this .drag.value.now[ this .axis];
// 边界处理
position = position.limit( - this .options.offset, this .full - this .options.offset);
// 计算当前的步数
this .step = Math.round( this .min + dir * this .toStep(position));
// 检查滑动位置有无变化
this .checkStep();
},
// 检查步数有无变化
checkStep: function () {
// 两值不等说明有改变
if ( this .previousChange != this .step) {
// 更新旧值
this .previousChange = this .step;
// 触发onChange事件,传送当前步数作参数
this .fireEvent( ' onChange ' , this .step);
}
},
// 结束滑动,检查步数有无变化
end: function () {
// 两值不等说明有改变
if ( this .previousEnd !== this .step) {
// 更新旧值
this .previousEnd = this .step;
// 触发onComplete事件,传送当前步数作参数
this .fireEvent( ' onComplete ' , this .step + '' );
}
},
// 根据鼠标位置计算当前的步数
toStep: function (position) {
var step = (position + this .options.offset) * this .stepSize / this .full * this .steps;
return this .options.steps ? Math.round(step -= step % this .stepSize) : step;
},
// 根据当前的步数计算滑块的位置
toPosition: function (step) {
return ( this .full * Math.abs( this .min - step)) / ( this .steps * this .stepSize) - this .options.offset;
}
});
// 演示:http://demos.mootools.net/Slider
var Slider = new Class({
// 继承实现Events和Options,UI插件的特征
Implements: [Events, Options],
options: { /*
//位置改变事件
onChange: $empty,
//拖动改变位置完成事件
onComplete: $empty, */
// 每一步的事件
onTick: function (position) {
// 如果指定吸附,根据步数计算位置
if ( this .options.snap) position = this .toPosition( this .step);
// 设置滑块的位置
this .knob.setStyle( this .property, position);
},
snap: false ,
// 偏移量
offset: 0 ,
// 指定滑动范围
range: false ,
// 滚轮支持
wheel: false ,
// 总步数
steps: 100 ,
// 滑动模式,水平或纵向
mode: ' horizontal '
},
// 构造函数,需要三个参数
// element为滑块所在容器,knob为滑块
initialize: function (element, knob, options) {
// 合并参数
this .setOptions(options);
// 取滑块所在的容器对象
this .element = $(element);
// 滑块
this .knob = $(knob);
// 初始化位置标记变量
this .previousChange = this .previousEnd = this .step = - 1 ;
// 添加鼠标按下的事件监听,实现点击时自动滑到指定位置
this .element.addEvent( ' mousedown ' , this .clickedElement.bind( this ));
// 如果设置支持滚轮,为容器添加滚轮监听事件
if ( this .options.wheel) this .element.addEvent( ' mousewheel ' , this .scrolledElement.bindWithEvent( this ));
// 初始化
var offset, limit = {}, modifiers = { ' x ' : false , ' y ' : false };
// 根据不同滑动模式初始化变量值
switch ( this .options.mode) {
// 纵向滑动时
case ' vertical ' :
// 别名为y轴方向
this .axis = ' y ' ;
// 这时主要是需要改变滑块CSS属性中的top
this .property = ' top ' ;
// 此时需要取值的属性为offsetHeiht
offset = ' offsetHeight ' ;
break ;
// 横向滑动时
case ' horizontal ' :
// 别名为x轴方向
this .axis = ' x ' ;
// 这时主要是需要改变滑块CSS属性中的left
this .property = ' left ' ;
// 此时需要取值的属性为offsetWidth
offset = ' offsetWidth ' ;
}
// 取滑块在当前滑动方向上的尺寸的一半
this .half = this .knob[offset] / 2 ;
// 计算滑块移动的总距离
this .full = this .element[offset] - this .knob[offset] + ( this .options.offset * 2 );
// 取范围的下限,默认为0
this .min = $chk( this .options.range[ 0 ]) ? this .options.range[ 0 ] : 0 ;
// 取范围的上限,默认为滑动的总步数
this .max = $chk( this .options.range[ 1 ]) ? this .options.range[ 1 ] : this .options.steps;
// 计算范围值
this .range = this .max - this .min;
// 总步数,如果steps参数值为0,则设为滑块移动的总距离
this .steps = this .options.steps || this .full;
// 计算每滑动一步的距离
this .stepSize = Math.abs( this .range) / this .steps;
// 计算每一步所占的宽度(根据上面的等级,这里不如直接用this.stepWidth = this.full/this.steps)
this .stepWidth = this .stepSize * this .full / Math.abs( this .range) ;
// 滑块相对于容器为相对定位
this .knob.setStyle( ' position ' , ' relative ' ).setStyle( this .property, - this .options.offset);
// 当前方向上对应的属性,转化用于Drag类的参数
modifiers[ this .axis] = this .property;
// 滑块的坐标范围
limit[ this .axis] = [ - this .options.offset, this .full - this .options.offset];
// 使滑块可拖动
this .drag = new Drag( this .knob, {
snap: 0 ,
// 滑块的可拖动范围
limit: limit,
// 指定拖动的方向及对应属性
modifiers: modifiers,
onDrag: this .draggedKnob.bind( this ),
onStart: this .draggedKnob.bind( this ),
onComplete: function () {
this .draggedKnob();
this .end();
}.bind( this )
});
// 如果指定吸附值
if ( this .options.snap) {
// 滑块拖动将网格化,单元格边长为滑动每一步所占的宽度
this .drag.options.grid = Math.ceil( this .stepWidth);
// 改变移动范围的上限,此时忽略偏移量
this .drag.options.limit[ this .axis][ 1 ] = this .full;
}
},
// 设置值
set: function (step) {
// 当范围上下限从小到大并且当前步值小于下限,或当范围上下限从大到小并且当前步值大于下限时,设置步值为下限值
if ( ! (( this .range > 0 ) ^ (step < this .min))) step = this .min;
// 当范围上下限从小到大并且当前步值大于是限,或当范围上下限从大到小并且当前步值小于上限时,设置步值为上限值
if ( ! (( this .range > 0 ) ^ (step > this .max))) step = this .max;
// 计算步数
this .step = Math.round(step);
// 检查步数变化,以决定是否触发事件
this .checkStep();
// 结束滑动
this .end();
// 触发步进事件
this .fireEvent( ' onTick ' , this .toPosition( this .step));
return this ;
},
// 点击直接跳到指定位置
clickedElement: function (event) {
// 判断方向
var dir = this .range < 0 ? - 1 : 1 ;
// 取当前模式下的鼠标在容器内的偏移值
var position = event.page[ this .axis] - this .element.getPosition()[ this .axis] - this .half;
// 边界处理
position = position.limit( - this .options.offset, this .full - this .options.offset);
// 计算步数
this .step = Math.round( this .min + dir * this .toStep(position));
// 检查步数变化,以决定是否触发事件
this .checkStep();
// 结束滑动
this .end();
// 触发步进事件
this .fireEvent( ' onTick ' , position);
},
// 利用滚轮跳到指定位置
scrolledElement: function (event) {
// 横向滑动和纵向滑动时,滚轮前滚和后滚导致的滑块的变化方向相反
var mode = ( this .options.mode == ' horizontal ' ) ? (event.wheel < 0 ) : (event.wheel > 0 );
// mode为真是向小值(左上)滑动,返之向大值(右下)滑动
this .set(mode ? this .step - this .stepSize : this .step + this .stepSize);
// 阻止事件冒泡及返回值
event.stop();
},
// 滑块移动时的处理
draggedKnob: function () {
// 判断方向
var dir = this .range < 0 ? - 1 : 1 ;
// 取当前模式下的鼠标坐标值
var position = this .drag.value.now[ this .axis];
// 边界处理
position = position.limit( - this .options.offset, this .full - this .options.offset);
// 计算当前的步数
this .step = Math.round( this .min + dir * this .toStep(position));
// 检查滑动位置有无变化
this .checkStep();
},
// 检查步数有无变化
checkStep: function () {
// 两值不等说明有改变
if ( this .previousChange != this .step) {
// 更新旧值
this .previousChange = this .step;
// 触发onChange事件,传送当前步数作参数
this .fireEvent( ' onChange ' , this .step);
}
},
// 结束滑动,检查步数有无变化
end: function () {
// 两值不等说明有改变
if ( this .previousEnd !== this .step) {
// 更新旧值
this .previousEnd = this .step;
// 触发onComplete事件,传送当前步数作参数
this .fireEvent( ' onComplete ' , this .step + '' );
}
},
// 根据鼠标位置计算当前的步数
toStep: function (position) {
var step = (position + this .options.offset) * this .stepSize / this .full * this .steps;
return this .options.steps ? Math.round(step -= step % this .stepSize) : step;
},
// 根据当前的步数计算滑块的位置
toPosition: function (step) {
return ( this .full * Math.abs( this .min - step)) / ( this .steps * this .stepSize) - this .options.offset;
}
});