样式说明:css
CSS ::-webkit-scrollbar { /* 1 */ } ::-webkit-scrollbar-button { /* 2 */ } ::-webkit-scrollbar-track { /* 3 */ } ::-webkit-scrollbar-track-piece { /* 4 */ } ::-webkit-scrollbar-thumb { /* 5 */ } ::-webkit-scrollbar-corner { /* 6 */ } ::-webkit-resizer { /* 7 */ }
::-webkit-scrollbar 滚动条总体部分,其中的属性有width,height,background,border(就和一个块级元素同样)等。 ::-webkit-scrollbar-button 滚动条两端的按钮。能够用display:none让其不显示,也能够添加背景图片,颜色改变显示效果。 ::-webkit-scrollbar-track 外层轨道。能够用display:none让其不显示,也能够添加背景图片,颜色改变显示效果。 ::-webkit-scrollbar-track-piece 内层轨道,滚动条中间部分(除去)。 ::-webkit-scrollbar-thumb 滚动条里面能够拖动的那部分 ::-webkit-scrollbar-corner 边角 ::-webkit-resizer 定义右下角拖动块的样式
一、 引入外部文件html
<script src="js/jquery.js"></script>jquery
<script src="js/jquery.nicescroll.min.js"></script>git
nicescroll是基于jquery的扩展,此处须要先引入jquery再引入nicescroll。angularjs
封装的ng-scroll指令代码以下:github
angular.module('ng.Scroll', []) .provider('$scroll', function(){ var $$options = { cursorcolor: "#008fd4",//改变滚动条颜色,使用16进制颜色值 cursoropacitymax: 0.2, //当滚动条是隐藏状态时改变透明度, 值范围 1 到 0 cursorwidth: "4px", //滚动条的宽度,单位:便素 cursorborder: "0", // CSS方式定义滚动条边框 cursorborderradius: "2px",//滚动条圆角(像素) autohidemode: false //隐藏滚动条的方式 }; //调用scrollProvider为整个项目配置统一的滚动条风格 this.setOptions = function(options) { angular.extend($$options, options); }; this.$get = function() { return { getOptions:function(){ //返回配置对象的一个拷贝 var defaultOptions={}; angular.copy($$options,defaultOptions); return defaultOptions; } }; } }) .directive('ngScroll', ['$scroll', function ($scroll) { return { restrict: 'A', link: _link }; function _link(scope, iElement, iAttrs) { var scrollOptions = scope.$eval(iAttrs.scrollOption);//解析scroll特性配置对象 var defaultOptions = $scroll.getOptions();//获取统一风格的配置对象 var niceOptions = angular.extend(defaultOptions, scrollOptions); var niceScroll = $(iElement).niceScroll(niceOptions); //调用第三方插件nicescroll方法对dom元素实现滚动条效果 scope.$on('$destroy', function () { // 注册'$destroy'事件来删除任何易于内存泄漏的代码。 if (angular.isDefined(niceScroll)) { niceScroll.remove() } }) } }]);
另外注意:nicescroll是把滚动条DOM节点全加在父容器上,当在同一页面中使用多个nicescroll滚动条时,滚动容器的滚动条时会影响内部的滚动条位置,要及时隐藏用完的nicescroll对象,web
加载时,须要先show,再resize。浏览器
因为这个缘由,使用多滚动条须要先隐藏滚动条的显示,仍是知足不了任务的需求,因此有了第三种方案。dom
此插件有JS和Jquery双版本,我更喜欢引入原生的js版,性能好也没必要依赖jquery库,插件的使用介绍直接看官方文档 https://github.com/noraesae/perfect-scrollbaride
在结合本身项目控件使用时带来了另外一个难题,perfect-scrollbar能解决多滚动条场景的BUG,但引入了另外一个BUG,好比表格Table中使用滚动条,在表格数据还没请求成功时,元素的scrollHeight高度为0,致使
perfect-scrollbar在初始化滚动条时,没法获得元素的具体高度scrollHeight,从而滚动条的高度为0,结果一开始滚动条是不显示的,鼠标在表格上滚动一下滚动条就出来了。
那么问题来了,如何解决Ajax请求的数据还未加载时,内容的高度还不肯定的状况怎么设置滚动条呢?
1,最原始的办法就是把初始化滚动条的操做放在Ajax请求的回调函数中,可是每一个与数据有关的地方须要滚动条显示时也是得都要进行此处理,使用不方便,并且Ajax请求通常都封装成单独的数据服务模块,滚动条逻辑和数据服务扯上关系了这有点尴尬,同时也增长了模块间的耦合性。
2,可使用事件监听,监听内容区域DOM元素的resize事件,当内容改变时就能自动增长元素的高度,就能够在监听函数中处理滚动条的更新。
当调整浏览器窗口的大小时,发生 resize 事件。也就是说,resize 事件触发在window对象上,window.addEventListener("resize",fn);
有个大神写了个方法能够在div上监听resize事件,直接就能够 $('div').resize(fucntion(){ .. }); 详情请看我另外一篇文章的记录:http://www.cnblogs.com/weboey/p/6014966.html
3,最佳解决办法。HTML5的新特性MutationObserver,它的做用是监视DOM变更。当DOM对象树发生任何改变时,MutationObserver会获得通知。有关MutationObserver的详细介绍和使用本文就不详细介绍 了,(HTML5此接口很强大,值得你们去学习了解)如下是我利用MutationObserver来解决内容元素的变更更新滚动条高度的代码,并封装成angularjs指令,直接以属性的形式使用。
define(['perfect-scrollbar','css!ng.Scroll'], function(perfectScroll) { angular.module('ng.Scroll', []) .directive('ngScroll', [function () { return { restrict: 'A', link: _link }; function _link(scope, iElement) { var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var hlazyresize=null; var container = iElement[0]; iElement.css({position: 'relative',overflow: 'hidden'}); //滚动条容器必要的样式 perfectScroll.initialize(container); //初始化滚动条 perfectScroll.lazyResize=function(){ //DOM元素内容不肯定是否加载完,滚动条进行延时加载处理 if (hlazyresize) clearTimeout(hlazyresize); hlazyresize = setTimeout(function(){ perfectScroll.update(container); },200); }; perfectScroll.lazyResize(); if(!!MutationObserver) { //观察配置对象,观察全部子节点(包括子节点和子节点的子节点) var observerOption={ 'childList': true, 'subtree': true }; //观察DOM树变更,更新滚动条 perfectScroll.observer=new MutationObserver( function(mutations){ perfectScroll.lazyResize(); } ).observe(container, observerOption); //观察滚动条注销,取消观察 perfectScroll.observerRemover = new MutationObserver( function(mutations) { mutations.forEach(function(mo) { if (mo.removedNodes.length > 0) { for (var dom in mo.removedNodes) { if (!!perfectScroll && (mo.removedNodes[dom] == container)) { perfectScroll.observer.disconnect(); perfectScroll.destroy(container); } } } }); }).observe(container.parentNode, observerOption); } scope.$on('$destroy', function () { // 注册'$destroy'事件来删除任何易于内存泄漏的代码。 if (angular.isDefined(container)) { perfectScroll.destroy(container); !!hlazyresize&&clearTimeout(hlazyresize); } }); } }]); });
工做中都会遇到一些大大小小问题,与你们分享一下任务的完成过程。鉴于本身的技术也菜,若是有更好的办法或者编码不严谨的地方欢迎你们纠正,请留在评论里供你们学习,一块儿共勉,谢谢。