首页 > 网站 > WEB开发 > 正文

js模拟滚动条(不依赖jquery)

2024-04-27 14:08:11
字体:
来源:转载
供稿:网友

js模拟滚动条(不依赖jquery)

转载请注明:TheViperhttp://www.cnblogs.com/TheViper

当页面中有很多滚动条,它们相互嵌套,很不好看,这时就会模拟滚动条,并给这个滚动条好看的样式,使得页面美观。

模拟滚动条很多时候是去用jquery插件,然后写几行代码就搞定了。不过随着mvvm的快速发展,很多时候都懒得用jquery了,这就是本文的动机,本屌力求用简单的不依赖jquery只依赖mvvm(avalon) api的代码,完成一个简易的滚动条。

要求:

1.鼠标滚轮可以让滚动条工作,界面滚动

2.鼠标可以拖动滚动条并让界面滚动

3.页面resize时,滚动条根据页面尺寸变化,仍然可以工作

效果:

很显然,这个组件是基于拖动drag的,本屌又不想重新写,就只有改下ui框架的drag了,这里改的是easy js ui的drag组件。用easy js是因为注释比较多,代码简洁。

本屌把easy js ui的drag组件里的相应方法换成avalon api里的方法,删掉PRototype里的方法及冗余代码

  1 define('drag',['avalon-min'],function(avalon){  2     function getBoundary(container, target) {  3         var borderTopWidth = 0, borderRightWidth = 0, borderBottomWidth = 0, borderLeftWidth = 0, cOffset = avalon(container)  4         .offset(), cOffsetTop = cOffset.top, cOffsetLeft = cOffset.left, tOffset = avalon(target)  5         .offset();  6         borderTopWidth = parseFloat(avalon.CSS(container,'borderTopWidth'));  7         borderRightWidth = parseFloat(avalon.css(container,'borderRightWidth'));  8         borderBottomWidth = parseFloat(avalon.css(container,'borderBottomWidth'));  9         borderLeftWidth = parseFloat(avalon.css(container,'borderLeftWidth')); 10         cOffsetTop = cOffsetTop - tOffset.top + parseFloat(avalon(target).css('top')); 11         cOffsetLeft = cOffsetLeft - tOffset.left + parseFloat(avalon(target).css('left')); 12         return { 13             top : cOffsetTop + borderTopWidth, 14             right : cOffsetLeft + avalon(container).outerWidth() - avalon(target).outerWidth() 15             - borderRightWidth, 16             left : cOffsetLeft + borderLeftWidth, 17             bottom : cOffsetTop + avalon(container).outerHeight() - avalon(target).outerHeight() 18             - borderBottomWidth 19         }; 20     } 21     var drag = function(target, options) { 22         var defaults = { 23             axis:null, 24             container:null, 25             handle:null, 26             ondragmove:null 27         }; 28         var o =avalon.mix(defaults,options), 29         doc = target.ownerDocument, 30         win = doc.defaultView || doc.parentWindow, 31         originHandle=target, 32         isIE =!-[1,], 33         handle = isIE ? target :doc, 34         container = o.container ?o.container: null,  35         count = 0, 36         drag = this,         37         axis = o.axis,         38         isMove = false,  39         boundary, zIndex, originalX, originalY, 40         clearSelect = 'getSelection' in win ? function(){ 41             win.getSelection().removeAllRanges(); 42         } : function(){ 43             try{ 44                 doc.selection.empty(); 45             } 46             catch( e ){}; 47         }, 48         down = function( e ){ 49             o.isDown = true;                50             var newTarget = target, 51             left, top, offset; 52             o.width = avalon(target).outerWidth(); 53             o.height = avalon(target).outerHeight(); 54             o.handle = handle; 55             left = avalon(newTarget).css( 'left' ); 56             top = avalon(newTarget).css( 'top' );          57             offset = avalon(newTarget).offset(); 58             drag.left = left = parseInt( left ); 59             drag.top = top = parseInt( top ); 60             drag.offsetLeft = offset.left; 61             drag.offsetTop = offset.top; 62             originalX = e.pageX - left; 63             originalY = e.pageY - top;  64             if( (!boundary && container)){ 65                 boundary = getBoundary(container, newTarget );   66             }   67             if( axis ){ 68                 if( axis === 'x' ){ 69                     originalY = false; 70                 } 71                 else if( axis === 'y' ){ 72                     originalX = false; 73                 } 74             } 75             if( isIE ){ 76                 handle.setCapture(); 77             } 78             avalon.bind(handle,'mousemove',move); 79             avalon.bind(handle,'mouseup',up); 80             if( isIE ){ 81                 avalon.bind(handle,'losecapture',up); 82             } 83             e.stopPropagation(); 84             e.preventDefault();    85         }, 86         move = function( e ){ 87             if( !o.isDown ){ 88                 return; 89             }             90             count++; 91             if( count % 2 === 0 ){ 92                 return; 93             } 94             var currentX = e.pageX, 95             currentY = e.pageY, 96             style = target.style, 97             x, y, left, right, top, bottom; 98             clearSelect(); 99             isMove = true;100             if( originalX ){101                 x = currentX - originalX;102                 if( boundary ){103                     left = boundary.left;104                     right = boundary.right;105                     x = x < left ? left : 106                     x > right ? right :107                     x;108                 }    109                 drag.left = x;110                 drag.offsetLeft = currentX - e.offsetX;111                 style.left = x + 'px';112             }113             if( originalY ){114                 y = currentY - originalY;115                 if( boundary ){116                     top = boundary.top;117                     bottom = boundary.bottom;118                     y = y < top ? top : 119                     y > bottom ? bottom :120                     y;121                 }    122                 drag.top = y;123                 drag.offsetTop = currentY - e.offsetY;124                 style.top = y + 'px';125             }126             o.ondragmove.call(this,drag);127             e.stopPropagation();   128         },129         up = function( e ){130             o.isDown = false;131             if( isIE ){132                 avalon.unbind(handle,'losecapture' );133             }134             avalon.unbind( handle,'mousemove');135             avalon.unbind( handle,'mouseup');136             if( isIE ){137                 handle.releaseCapture();138             }139             e.stopPropagation();                140         }; 141         avalon(originHandle).css( 'cursor', 'pointer' );142         avalon.bind( originHandle,'mousedown', down );143         drag.refresh=function(){144             boundary=getBoundary(container,target);145         };    146     };147     return drag;148 });
View Code

另外在最后暴露的drag上加了一个refresh()方法,作用是在resize时,需要更新滚动条可以拖动的范围。这个方法在scrollbar的更新视图中会用到。

        drag.refresh=function(){            boundary=getBoundary(container,target);        }; 

还有在滚动条拖动过程move中,添加一个钩子,允许从外面添加一个监听函数,拖动时会触发监听函数,并传入drag参数。

o.ondragmove.call(this,drag);

然后是scrollbar.js

 1 define('scrollbar',['avalon-min','drag'],function(avalon,drag){ 2     function scrollbar(wrap,scrollbar,height_per_scroll){//容器,滚动条,每次滚轮移动的距离 3         this.scroll_height=0;//滚动条高度 4         this.dragger=null;//drag组件实例 5         wrap.scrollTop=0; 6         //容器的位置要减去浏览器最外面的默认滚动条垂直方向位置 7         var self=this,wrap_top=avalon(wrap).offset().top-avalon(document).scrollTop(); 8         function ondragmove(drag){//drag组件拖动时的监听函数,更新容器视图 9             wrap.scrollTop=(parseFloat(scrollbar.style.top)-wrap_top)*10             (wrap.scrollHeight -wrap.clientHeight)/(wrap.clientHeight-self.scroll_height);11         };12         function setScrollPosition(o) {//更新滚动条位置13             scrollbar.style.top =o.scrollTop*wrap.clientHeight/wrap.scrollHeight+wrap_top+ 'px';14         }15         function inti_events(){16
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表