javascript jscroll模拟超文本标记语言元素滚动条
主流浏览器默认为html元素提供的滚动条并不美观,前端开发者也不可能通过css统一样式美化。比如ie可以通过样式实现简单美化,Webkit内核浏览器可以控制滚动条的显示效果,firefox不允许用户为滚动条定义样式。然而,寻求友好用户体验的前端开发人员不会被这些浏览器的不一致行为所阻止。我们可以通过标准的html元素模拟来实现自定义滚动条。在这里,当我工作不太忙的时候,我写了一个用户定义的滚动条jscroll。Jscroll默认只提供一种滚动条样式,部分来自google webstore,部分css3样式主要用于实现圆角和阴影效果。为了实现滚动条跨浏览器一致的显示效果,针对ie6、7、8中不支持css3的浏览器引入了PIE.htc文件。分别说明了以下功能和兼容性、用法以及具体的代码实现。实现功能和兼容性jscroll实现了默认滚动条几乎所有的功能,比如拖动滚动条查看内容,滚动鼠标滚轮查看内容,点击滚动条可以到达的区域的上部或下部触发滚动条的滚动,使用键盘上下键触发滚动条的滚动。火狐、chrome、ie9等最新的浏览器都支持最新的css3和js的API,所以不存在兼容性问题。IE 6、7、8不支持css3通过引入PIE.htc的hack文件来做兼容处理js的方面是通过旧的API兼容不支持的API。兼容性问题最大的浏览器是ie6,不支持点击滚动条可达区域触发滚动条滚动,也不支持键盘上下键触发滚动条滚动。出现这个问题的主要原因是引入了支持css3的PIE.htc文件。如果不引入hack文件,所有的操作都可以支持,不可能做到。为了显示效果一致,不得不选择一些不支持的功能。该方法在页面的弹出层或页面的某个区域最常使用自定义滚动条。永远不要自定义整个页面的滚动条。对于需要使用jscroll的元素,需要添加自定义属性data-scroll='true '来告诉程序需要使用jscroll来替换系统默认的滚动条,还需要添加自定义属性data-width=' ',data-height=' '来指定要显示的元素的宽度和高度。Jscroll根据用户自定义的宽度和高度计算内容的显示宽度和滚动条的显示高度,并添加交互事件。实现jscroll的逻辑并不复杂,实现特定功能的js代码不到400行,但是依赖于一些基本方法,所以需要引入squid.js作为基本方法的支持。控制滚动条样式的css在一个单独的jscroll-1.0.css文件中,用户可以根据自己的需要进行修改和扩展。下面简单分析一下每个方法实现的具体功能:复制代码如下: init : function(selector,context){ selecotr=selector | | ' data-scroll ' Context=Context | | document var elems=squid . getelementsbyattribute(selector,Context)这个。initview (elems)} init()是一个初始化函数,它根据指定的选择器和上下文获取需要使用自定义滚动条的元素。选择器默认为数据滚动,上下文默认为当前文档。在这里,无论元素的自定义属性数据-scroll='true '还是数据-scroll='false ',系统默认滚动条都会被自定义滚动条覆盖。squid的getElementsByAttribute()方法只提供根据元素是否具有指定的属性来查找元素,而忽略属性值。这个方法不如jquery选择器或高级浏览器提供的querySelectorAll()方法强大,因为squid在这里只提供最基本的支持。找到需要自定义滚动条的元素后,调用initView方法初始化滚动条的整体结构和显示。
复制代码代码如下:initView:函数(elems) { var i=0,length=elems.length,elem;for(;一、长度;I){ elem=elems[I]if(这个。hascroll(elem)){这个。创建(elem)} }这个。initevent()} initView()方法会首先对页面上获取的带有自定义属性数据滚动的元素遍历,判断每一个元素是否会出现滚动条,通过hasScroll()方法判断。如果元素会出现滚动条则调用创建()方法分别创建自定义的滚动条initView()方法结束会调用initEvent()方法。复制代码代码如下://是否有滚动条哈斯克罗:函数{返回elem。补偿加热元件。滚动高度} hasScroll()方法用于判断元素是否会出现滚动条,返回真实的或者假的。这里忽略元素的边缘和填充,通过jscroll创建的滚动条默认边缘和填料都是0。复制代码代码如下://创建滚动条元素整体结构create:函数(elem) { var包装器,列表,//滚动条元素s,//带滚动条元素显示的高度height=elem[' data-height ']| | elem。GetAttribute('数据高度'),//带滚动条元素显示的宽度width=elem[' data-width ']| | elem。GetAttribute('数据宽度'),//滚动条显示高度价值;//包装器包装器=文档。createelement(' div ')包装。类名=' jscroll-wrapper '/禁止选择文本,对于ie9/* *包装。onselectstart=function(){ * return false * } */squid。CSS(包装器,{ height: height 'px,width : width ' px ' })squid。addclass(elem,' jscroll-body ')//覆盖用户定义样式的squid.css(elem,{ overflow: 'visible ',position : { height :(height-5)' px ' })//滚动条s=文档。创建元素(' div '),类名=' jscroll-拖动不可选择的s。不可选择的='on' s.setAttribute('tabindex ',' 1') s.setAttribute('hidefocus ',true)列表。appendchild包装。appendchild(列表)//把需要出现滚动条的元素包裹起来elem.parentNode.replaceChild(包装,elem)包装。插入之前(elem,list) //滚动条高度值=这个。scrollbarheight(elem,height) squid.css(s,{ height : value ' px ' })/add event this。regevent(包装)} create()方法用户调整创建带有自定义滚动条的元素整体结构,首先通过创建了包装材料元素,用于包装会出现滚动条的元素elem和滚动条可滚动的区域元素目录以及滚动条元素s。通过从出现滚动条元素设置的自定义属性数据宽度、数据高度分别设置包装材料元素的宽度和高度。通过滚动条高度()方法计算得到了滚动条元素显示的高度,整体结构不算复杂。创建自定义滚动条整体结构之后是为滚动条元素s和滚动条可到达区域元素目录添加事件处理,通过regEvent()方法实现。复制代码代码如下://计算滚动条的高度滚动条高度:函数(elem,高度){ var值=elem。滚动高度;返回(高度/值)*高度}滚动条高度()方法通过简单的数学计算返回滚动条元素应该显示的高度。
复制代码代码如下: initevent :函数(){ var即=this,_default,elem,top,min,max,prev,parent,sbody,unit//滚动条滚动squid.on(文档,‘mouse move’,函数(事件){ elem=that。滚动。elem if(elem!==null) { squid.addClass(elem,' scrolling ')top=event。客户-那个。滚动。不同的父母。ie6?艾伦。父节点。父节点: elem。父节点min=那个。极限值.最小值最大值=那个。极限值.max prev=父级。previoussiblingsbody=prev。标记名。tolowercase()===' div '?prev : prev。previoussibling _ default=parsent(s body[' data-height ']| | s body。getattribute(' data-height '),10)unit=(sbody。scroll height-_ default)/max squid。addclass(sbody。parentnode不可选择)if(top min){ top=min } else if(top max){ top=max } elem。风格。top=顶部“px”表示。doscoll(sbody,top * unit)})//滚动结束squid.on(文档,‘mouse up’,函数(事件){ elem=that。滚动。elem if(elem){ prev=那个。ie6?艾伦。parentnode。parentnode。先前的兄弟: elem。parentnode。previoussibling sbody=prev。标记名。tolowercase()===' div '?prev : prev。前兄弟乌贼。移除类(sbody。父节点不可选择)}那个。滚动。elem=空。滚动。diffy=0 })initEvent()方法实现了为文件元素添加鼠标移动和鼠标向上事件,鼠标移动实现了在拖动滚动条元素滚动时查看的内容跟随变化。代码首先判断当前是否有拖动滚动条查看内容的操作,如果有就计算滚动条被拖动到的位置,然后计算查看内容应该到的地方。代码里对ie6的判断,是因为引入的PIE.htc文件破坏了原有的结构(为了实现跨浏览器下显示效果的一致,付出太大了!)。鼠标向上事件处理程序实现了清除上次操作的滚动条元素。
复制代码代码如下://添加滚动条事件regEvent:函数(elem){ var=this,sbody=elem.firstChild,list=sbody.nextSibling,//滚动条元素s=list.firstChild,//滚动条滚动最小值最小值=0,//滚动条滚动最大值max=list。offset thight-s . offset thight,_ default=parsent(s body[' data-height ']| | s body。getattribute(' data-height '),10),unit=(sbody。scroll height-_ default)/max//Firefox浏览器Firefox=' MozBinding '在文档中。文档元素。样式,//鼠标滚轮事件mousewheel=firefox?DOMMouseScroll ' : ' mousewheel ',//opera浏览器歌剧=窗户。驾驶领航员。用户代理。indexof(' MSIE ')===-1,//正在激发鼠标放下事件激发=false,//鼠标点击,定时器执行时间间隔,//滚动条距离容器高度top,//滚动条当前顶端值cur,//每次滚动多少像素速度=18;//变量缓存min,max this.limits[s]={ min: 0,max: max } //scroll事件鼠标滑动滚轮移动滚动条squid.on(elem,mousewheel,function(event){ var delta;if(事件。车轮){=opera?事件。车轮三角/120 :事件。车轮增量/120 } else {增量=-事件。detail/3 } cur=parsent(s . style。top | | 0,10) //向上滚动if(0){ top=当前速度if(top min) { top=min } }else{//向下滚动top=cur速度if(top max){ top=max } } s . style。top=顶部“px”表示。doscoll(sbody,top * unit) //阻止身体元素滚动条滚动event.preventDefault() }) //ie6,7,8下,如果鼠标连续点击两次且时间间隔太短,则第二次事件不会触发//拖动滚动条,点击滚动条可到达区域squid.on(list,' mousedown ',function(event){ var target=event。target,y=event.clientYtarget=event。目标if(目标。标记名。tolowercase()===' shape ')目标=s//鼠标点击元素是滚动条if(target===s){//调用elem setCapture s . setCapture s . setCapture()即。滚动。diffy=y-s . offsettop//鼠标移动过程中判断是否正在拖动滚动条那个。滚动。elem=s } else if(target。类名。match(' jscroll-list '){ firing=true interval=setInterval(function(){ if(firing){ that。鼠标手柄(列表,y,单位)} },80)})//鼠标松开滚动条停止滚动squid.on(list,' mouseup ',function(){//invoke elem release capture s . release capture s . release capture()firing=false clearInterval(interval)})//滚动条元素获取焦点,可以触发按键事件squid.on(s,' click ',function() { this.focus() }) //滚动条获取焦点后,触发键盘上下键,滚动条滚动squid.on(s),' keydown ',function(event){ var key code=event。键码,状态=falsecur=parsent(s . style。top | | 0,10)开关(键码){ case 38: top=cur-speed if(top min){ top=min }状态=真断case 40: top=cur speed if(top max){ top=max }状态=真断默认3360 break } if(state){ s . style。top=顶部“px”表示。doscoll(sbody,top * unit)}活动。preventdefault()})regEvent方法实现了以下功能,应该是jscroll组件的核心方法了:1.鼠标在包含滚动条的元素区域,上下滚动鼠标滚轮,查看的内容跟随滚轮上下翻的功能2.点击滚动条可到达区域,即滚动条上方或者下方,滚动条和查看的内容向上或者向下滚动。鼠标点击滚动条可到达区域不松开,可连续滚动滚动条和查看的内容,通过调用mouseHandle()方法来具体实现该功能。
3.点击滚动条元素后,可以通过键盘的上下键触发滚动条,查看内容的滚动复制代码如下://当鼠标点击滚动条到达区域上方或下方时,滚动条滚动鼠标手柄:函数(elem,place,Unit){ var prev=elem . previous sibling,//包含滚动条显示内容元素a=prev . tagname . to lower case()==' div '?prev : pprev . previsible,//n=elem.firstchild,//滚动条元素s=this.ie6?n . LastChild :n . tagname . ToLowerCase()===' div '?N : n.nextSibling,//滚动条高度,//从列表元素到正文的顶值,//从滚动条到容器的顶值,//从滚动条到正文的顶值,//滚动条滚动最小值,//滚动条滚动最大值,//每次单击滚动条到达该区域时,滚动条都会上下移动10pxstep=10。//当与最上面或最下面区域的距离小于该距离时,滚动条可以自动移动到最上面或最下面的距离=20;min=this.limits[s]。min max=this.limits[s]。最大高度=s . offset ThEr top=ParSeint(s . style . top | | 0,10)值=squid。getoffset (elem)。topstop=鱿鱼。getoffset。top//单击滚动条下方的区域。向下滚动if(放置停止){if (valueelem。偏右距离(elem。偏高(顶部)距离){顶部=最大值}。else { if((stop-height step)=place){ top=step } else { top=place-value-height } } else {//当鼠标点击区域到滚动条顶部的距离小于滚动条的长度时,如果(place-value distance top distance){ top=min } else {//滚动条从页面顶部的高度减去鼠标clientY值大于step if(stop-place=step){ top-=step }。else { Top=place-value } } } if(Top min){ Top=min } else if(Top max){ Top=max } s . style . Top=Top ' px ' this . doscoroll(a,Top * unit) }mouseHandle()方法通过判断鼠标点击位置在页面中的位置坐标和滚动条元素在页面中的位置来判断是点击滚动条的上部区域还是下部区域。如果点击下方区域,滚动条将向下滚动,否则将向上滚动。当点击的位置在上区或下区小于距离值时,滚动条会自动滚动到最小值或最大值。显示效果这个控件的演示使用了淘宝用户注册协议的内容。因为火狐、chrome等高级浏览器可以保证良好的兼容性和显示效果,这里只显示ie低版本浏览器的显示效果。ie浏览器截图如下:ie6 下。
初始化后
轧制工艺
滚动至底部ie7 。
滚动条初始化后
轧制工艺
滚动至底部ie9 。
开始滚动之前
轧制工艺
滚动到底部总结:基础功能实现代码这么多,分析可能不够详细。最复杂的可能是位置计算和事件绑定处理。如有疑问,欢迎大家交流、学习、交流。注意:PIE.htc文件的路径要放对,引用时要写成绝对路径,否则IE6、7、8下不会有css3效果(如果是这样,我代码中做的兼容性处理就没有意义了!),如果需要更改引用路径,可以在jscroll-1.0.css文件中进行修改。最后,附上源代码。欢迎有意者下载试用。
版权声明:javascript jscroll模拟超文本标记语言元素滚动条是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。