美化瀏覽器滾動條效果

任務需求:因爲不一樣瀏覽器對滾動條的樣式解析存在差別,爲統同樣式風格,增長總體美觀程度,須要實現自定義滾動條。

第一種方案:CSS設置滾動條樣式。(目前只有Chrome瀏覽器支持,火狐不支持)

樣式說明: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                       定義右下角拖動塊的樣式

 

第二種方案:因爲CSS設置滾動條只有谷歌瀏覽器支持,因此引入jquery第三方擴展插件nicescroll.js並對其進行封裝成AngularJs指令使其更方便使用。

一、 引入外部文件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

第三種方案:引入另外一個擴展插件perfect-scrollbar並對其進行封裝成AngularJs指令使其更方便使用。

 此插件有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);
                    }
                });
            }
        }]);
});

總結

工做中都會遇到一些大大小小問題,與你們分享一下任務的完成過程。鑑於本身的技術也菜,若是有更好的辦法或者編碼不嚴謹的地方歡迎你們糾正,請留在評論裏供你們學習,一塊兒共勉,謝謝。

相關文章
相關標籤/搜索