您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

原生js实现模拟滚动条_javascript技巧

2024/3/28 0:45:52发布11次查看
当页面中有很多滚动条,它们相互嵌套,很不好看,这时就会模拟滚动条,并给这个滚动条好看的样式,使得页面美观。
模拟滚动条很多时候是去用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里的方法及冗余代码
define('drag',['avalon-min'],function(avalon){ function getboundary(container, target) { var bordertopwidth = 0, borderrightwidth = 0, borderbottomwidth = 0, borderleftwidth = 0, coffset = avalon(container) .offset(), coffsettop = coffset.top, coffsetleft = coffset.left, toffset = avalon(target) .offset(); bordertopwidth = parsefloat(avalon.css(container,'bordertopwidth')); borderrightwidth = parsefloat(avalon.css(container,'borderrightwidth')); borderbottomwidth = parsefloat(avalon.css(container,'borderbottomwidth')); borderleftwidth = parsefloat(avalon.css(container,'borderleftwidth')); coffsettop = coffsettop - toffset.top + parsefloat(avalon(target).css('top')); coffsetleft = coffsetleft - toffset.left + parsefloat(avalon(target).css('left')); return { top : coffsettop + bordertopwidth, right : coffsetleft + avalon(container).outerwidth() - avalon(target).outerwidth() - borderrightwidth, left : coffsetleft + borderleftwidth, bottom : coffsettop + avalon(container).outerheight() - avalon(target).outerheight() - borderbottomwidth }; } var drag = function(target, options) { var defaults = { axis:null, container:null, handle:null, ondragmove:null }; var o =avalon.mix(defaults,options), doc = target.ownerdocument, win = doc.defaultview || doc.parentwindow, originhandle=target, isie =!-[1,], handle = isie ? target :doc, container = o.container ?o.container: null, count = 0, drag = this, axis = o.axis, ismove = false, boundary, zindex, originalx, originaly, clearselect = 'getselection' in win ? function(){ win.getselection().removeallranges(); } : function(){ try{ doc.selection.empty(); } catch( e ){}; }, down = function( e ){ o.isdown = true; var newtarget = target, left, top, offset; o.width = avalon(target).outerwidth(); o.height = avalon(target).outerheight(); o.handle = handle; left = avalon(newtarget).css( 'left' ); top = avalon(newtarget).css( 'top' ); offset = avalon(newtarget).offset(); drag.left = left = parseint( left ); drag.top = top = parseint( top ); drag.offsetleft = offset.left; drag.offsettop = offset.top; originalx = e.pagex - left; originaly = e.pagey - top; if( (!boundary && container)){ boundary = getboundary(container, newtarget ); } if( axis ){ if( axis === 'x' ){ originaly = false; } else if( axis === 'y' ){ originalx = false; } } if( isie ){ handle.setcapture(); } avalon.bind(handle,'mousemove',move); avalon.bind(handle,'mouseup',up); if( isie ){ avalon.bind(handle,'losecapture',up); } e.stoppropagation(); e.preventdefault(); }, move = function( e ){ if( !o.isdown ){ return; } count++; if( count % 2 === 0 ){ return; } var currentx = e.pagex, currenty = e.pagey, style = target.style, x, y, left, right, top, bottom; clearselect(); ismove = true; if( originalx ){ x = currentx - originalx; if( boundary ){ left = boundary.left; right = boundary.right; x = x right ? right : x; } drag.left = x; drag.offsetleft = currentx - e.offsetx; style.left = x + 'px'; } if( originaly ){ y = currenty - originaly; if( boundary ){ top = boundary.top; bottom = boundary.bottom; y = y bottom ? bottom : y; } drag.top = y; drag.offsettop = currenty - e.offsety; style.top = y + 'px'; } o.ondragmove.call(this,drag); e.stoppropagation(); }, up = function( e ){ o.isdown = false; if( isie ){ avalon.unbind(handle,'losecapture' ); } avalon.unbind( handle,'mousemove'); avalon.unbind( handle,'mouseup'); if( isie ){ handle.releasecapture(); } e.stoppropagation(); }; avalon(originhandle).css( 'cursor', 'pointer' ); avalon.bind( originhandle,'mousedown', down ); drag.refresh=function(){ boundary=getboundary(container,target); }; }; return drag;});
另外在最后暴露的drag上加了一个refresh()方法,作用是在resize时,需要更新滚动条可以拖动的范围。这个方法在scrollbar的更新视图中会用到。
drag.refresh=function(){ boundary=getboundary(container,target); };
还有在滚动条拖动过程move中,添加一个钩子,允许从外面添加一个监听函数,拖动时会触发监听函数,并传入drag参数。
o.ondragmove.call(this,drag);
然后是scrollbar.js
define('scrollbar',['avalon-min','drag'],function(avalon,drag){ function scrollbar(wrap,scrollbar,height_per_scroll){//容器,滚动条,每次滚轮移动的距离 this.scroll_height=0;//滚动条高度 this.dragger=null;//drag组件实例 wrap.scrolltop=0; //容器的位置要减去浏览器最外面的默认滚动条垂直方向位置 var self=this,wrap_top=avalon(wrap).offset().top-avalon(document).scrolltop(); function ondragmove(drag){//drag组件拖动时的监听函数,更新容器视图 wrap.scrolltop=(parsefloat(scrollbar.style.top)-wrap_top)* (wrap.scrollheight -wrap.clientheight)/(wrap.clientheight-self.scroll_height); }; function setscrollposition(o) {//更新滚动条位置 scrollbar.style.top =o.scrolltop*wrap.clientheight/wrap.scrollheight+wrap_top+ 'px'; } function inti_events(){ avalon.bind(wrap,'mousewheel',function(e){ if(e.wheeldelta < 0) wrap.scrolltop+=height_per_scroll; else wrap.scrolltop-=height_per_scroll; setscrollposition(wrap); e.preventdefault(); }); self.dragger=new drag(scrollbar,{container:wrap,axis:'y',ondragmove:ondragmove}); window.onresize=function(){ self.refresh_views(); self.dragger.refresh(); }; } this.refresh_views=function(){//更新组件所有部分视图,并暴露供外部调用 //容器高度这里设置成浏览器可视部分-容器垂直方向位置,没有考虑容器有border,padding,margin.可根据相应场景修改 wrap.style.height=document.documentelement.clientheight-wrap_top+'px'; self.scroll_height=wrap.clientheight*wrap.clientheight/wrap.scrollheight; //容器高度等于滚动条高度,隐藏滚动条 if(self.scroll_height==wrap.clientheight) scrollbar.style.display='none'; else scrollbar.style.display='block'; scrollbar.style.height=self.scroll_height+'px'; setscrollposition(wrap); } function init(){ self.refresh_views(); inti_events(); } init(); } return scrollbar;});
可以看到,在resize时,调用了drag组件的refresh方法,更新滚动条可以拖动的范围。这里暴露了refresh_views()方法,以应对外部需要手动更新视图的情况。比如,聊天分组的折叠和展开。
这样就完成了简易滚动条。代码很简单,如果出问题需要fix bug或定制的话,也很容易。
以上所述上就是本文的全部内容了,希望大家能够喜欢。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product