[转帖]Mootools源码分析-48 -- Slider

原帖地址: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;
    }
});

 

posted @ 2009-12-01 21:08  webgis松鼠  阅读(288)  评论(0编辑  收藏  举报