0 Comments

Slider实现的滑动条效果(4)

发布于:2013-07-12  |   作者:广州网站建设  |   已聚集:人围观

【鼠标拖动控制】

鼠标拖动控制,就是通过拖动滑块来设置定位。

这个就跟滚动条意思差不多,主要是通过_drag本身的拖放效果来实现的(详细看这里拖放效果)。
广州网站建设,网站建设,广州网页设计,广州网站设计

【鼠标点击控制】

鼠标点击控制,就是当点击容器的时候能定位到点击的位置。

一般来说只要把ClickCtrl鼠标点击控制程序绑定容器的click事件中就可以了。

但这里有个问题,滑块的点击(拖动控制)跟容器的点击会发生冲突,具体表现是拖放结束后就“顺便”触发了容器的click。

这个本来在滑块的点击事件中取消冒泡就可以:


  1. addEventHandler(this.Bar, "click", BindAsEventListener(thisfunction(e){ e.stopPropagation(); }));  

但ie的click机制有点问题:


  1. <div style="width:100px; height:100px; background-color:#CCC;" onclick="alert(1)" > 
  2. <div style=" height:50px; background-color:#C11;" onclick="event.stopPropagation?event.stopPropagation():(event.cancelBubble=true);" ></div> 
  3. </div> 

里面的div取消冒泡,点击它不会触发外面div的onclick,但如果在里面的div点,然拖动到外面的div放,就会触发了,而ff是不会的。

ps:从外面拖到里面也是一样的情况。

经过测试,我觉得是因为ie认为点击的点和放只要是发生在同一个元素的内部(包括内部的其他元素),那个这个点击就是有效的;而ff则认为点击的点和放必须在同一个元素内才有效(w3c标准应该也是这样)。

这个导致的问题是,当拖放结束时如果放开鼠标的地方是容器上,那么就会发生冲突了。

那对于ie的这个现象,解决方法其实也很多,我用的方法很简单,设一个属性_ondrag来表示是否拖放中。

具体就是在DragStart开始拖放滑动程序中把_ondrag设为true,并在DragStop结束拖放滑动程序中把它设为false:


  1. setTimeout(Bind(thisfunction(){ this._ondrag = false; }), 10);  

这里用了setTimeout,因为拖放结束后才会触发容器的click,所以设一个延时,使这个值在容器的click触发后才修改。

这样就可以通过这个_ondrag来判断是否应该执行ClickCtrl了:


  1. addEventHandler(this.Container, "click", BindAsEventListener(this, function(e){ this._ondrag || this.ClickCtrl(e);}));  

接着看ClickCtrl鼠标点击控制程序,首先获取容器的相对文档的位置:


  1. var o = this.Container, iLeft = o.offsetLeft, iTop = o.offsetTop;  
  2. while (o.offsetParent) { o = o.offsetParent; iLeft += o.offsetLeft; iTop += o.offsetTop; }  

注意,要逐级向上获取才能取得相对相对文档的位置。

然后通过pageX(pageY)和滑块(这里是要设置到滑块的中间位置所以取一半)得到要设置的位置:


  1. this.EasePos(e.pageX - iLeft - this.Bar.offsetWidth / 2, e.pageY - iTop - this.Bar.offsetHeight / 2);  

这里要用pageX(pageY)来取值,而不是clientX(clientY),因为后者是没有计算滚动条的。

ps:ie没有pageX(pageY),不过在Event程序中已经给window.event添加了这个属性:


  1. oEvent.pageX = oEvent.clientX + document.documentElement.scrollLeft;  
  2. oEvent.pageY = oEvent.clientY + document.documentElement.scrollTop;  

【鼠标滚轮控制】

鼠标滚轮控制,就是通过鼠标滚轮滚动来控制滑块的滑动。

首先ie绑定滚轮事件用的是mousewheel,ff用的是DOMMouseScroll,所以在WheelBind绑定鼠标滚轮程序中是这样设置的:


  1. addEventHandler(o, isIE ? "mousewheel" : "DOMMouseScroll", BindAsEventListener(thisthis.WheelCtrl));  

接着看WheelCtrl鼠标滚轮控制程序,通过event的detail属性可以获取鼠标滚动的距离(值大小)和方向(正负)。

利用它来设置要滑动的位置:


  1. var i = this.WheelSpeed * e.detail;  
  2. this.SetPos(this.Bar.offsetLeft + i, this.Bar.offsetTop + i);  

但ie没有detail,对应的有wheelDelta,wheelDelta的数值刚好是detail的40倍,而且方向相反(正负相反),所以Event程序中是这样给window.event添加detail的:


  1. oEvent.detail = oEvent.wheelDelta / (-40);  

为了防止触发其他滚动条,这里用了preventDefault取消默认动作。

注意不是用取消冒泡(貌似滚屏是事件的默认动作)。
广州网站建设,网站建设,广州网页设计,广州网站设计

【方向键控制】

方向键控制,就是通过键盘的左右(上下)方向键来控制滑块的滑动。

首先用KeyBind方向键绑定程序把KeyCtrl方向键控制程序绑定到对象的keydown事件中:


  1. addEventHandler(o, "keydown", BindAsEventListener(thisthis.KeyCtrl));  

在KeyCtrl中,通过event的keyCode属性获取键盘的按键(左37、上38、右39、下40)并进行相应的操作:


  1. switch (e.keyCode) {  
  2.     case 37 ://左  
  3.         iLeft -= iWidth; break;  
  4.     case 38 ://上  
  5.         iTop -= iHeight; break;  
  6.     case 39 ://右  
  7.         iLeft += iWidth; break;  
  8.     case 40 ://下  
  9.         iTop += iHeight; break;  
  10.     default :  
  11.         return;//不是方向按键返回  
  12. }  

同样为了防止触发其他滚动条,也用了preventDefault取消默认动作。

飞机