javascript控制項開發之捲軸控制項

來源:互聯網
上載者:User

javascript控制項開發之捲軸控制項
在網頁中,本身就有捲軸,在顯示常值內容的時候,原始的捲軸已夠用,一般如果我們想實現一個類似列表的控制項時,也可以把所有的列表資料輸出到一個完整的

標籤,再嵌入到一個DIV中即可,然而如果資料量達到幾千行時,完全產生






/** * 捲軸控制項. * 建立:QZZ * 日期:2014-03-01 */(function(undefined) {nameSpace("com.ui");/** * 捲軸控制項. */com.ui.scrollBar = Extend(com.ui.window, {    /**     * 建立函數     */    create:function() {    },    /**     * 渲染.     */    render:function() {    }});})();




/** * 建立函數 */create:function() {    this.base();            this.className = "com.ui.scrollBar";            this.logInfo("create");//綁定明細總數量this.scrollCount = 0;//顯示地區可見數量this.showCount = 0;//滾動位置this.scrollIndex = 0;//每步滾動像素長this.stepLen = 2;//拖動按鈕最短長this.dragBoxMinLen = 20;//橫、縱向捲軸this.option.scrollType = this.option.scrollType || "V";//捲軸是否可見this.visible = true;//按鈕寬度this.btnWidth = 15;//初始化寬高屬性if(this.option.scrollType == "V") {    this.option.width = this.option.width || 16;    this.option.height = this.option.height || 100;} else if(this.option.scrollType == "H") {    this.option.width = this.option.width || 100;    this.option.height = this.option.height || 16;}this.dragState = false;},


的話,將會非常的佔用記憶體,因此較好的辦法是用虛擬展示的方式, 所謂虛擬展示就是把資料用一個數組儲存, 然後只產生可見部分的DOM元素,比如可見行是10行,那就建立10個 ,通過重新整理的方式,在這10行中,滾動顯示所有的資料,這樣,捲軸就是主要的一環節, 以上的說明等到我們做後面的列表展示控制項時,大家就會明白,在此就不再詳細說明,接下來我們進入主題,開發我們的捲軸控制項。 本次我們做的滾動特性有,上、下兩個按鈕和拖動的按鈕,其餘特性遵照平時系統捲軸的規則來開發,其中捲動區域是通過設定明細數量來設定滾動數量,比如,總共有1000條資料,然後介面能顯示50條,那滾動數量則是1000-50條,通過這個資料來繪製捲軸的滾動數量,這種方式實現捲軸是為後續虛擬滾動做準備 首先,基於行前幾篇開發的的架構,我們在目錄 component\ui\下添加檔案 com.ui.scrollBar.js, 在檔案中定義com.ui.scrollBar類,繼承com.ui.window類,如下在捲軸的建立函數中定義一些基本屬性,如捲軸類型、滾動總數量、顯示數量、滾動位置、滾動一條的步長及拖動按鈕最短長度等,如下 定義好基本的屬性後,開始繪製捲軸的架構, 這裡我們採用
來實現, 比如縱向捲軸,則產生一個三行一列的

,第一行與第三行用作上下按鈕,中間用作捲動區域,(橫向的同理), 然後在捲動區域(上邊
的第二行)中又加入一個兩行一列的



    /**     * 渲染.     */    render:function() {        this.base();        //建立捲軸結構
,用作中間拖動按鈕,第一行,繪製邊線與背景相同,第二行繪製成按鈕,通過調整第一行的行高來設定按鈕的位置, 繪製完成後,添加按鈕的事件,及拖動事件, 如下:
if(this.scrollTable == null) { this.scrollTable = this.createElement("TABLE"); } //清除原有的行列,結構變化的時候,會有已存在行 while(this.scrollTable.rows.length > 0) { this.scrollTable.deleteRow(0); } //建立拖動按鈕結構




    /**     * 重新整理布局     */    refreshBox:function() {        var rw = this._getRectWidth(), rh = this._getRectHeight()        //設定按鈕的樣式及長、寬度,        if(this.option.scrollType == "V") {            this.priorBtn.style.height = this.btnWidth - 1 + "px";            this.setStyle(this.priorBtn, "scrollUp");            this.centerRect.style.height = (rh - 2 * this.btnWidth) + "px";            this.setStyle(this.centerRect, "scrollCell");            this.nextBtn.style.height = this.btnWidth - 1 + "px";            this.setStyle(this.nextBtn, "scrollDown");            this.dragTable.style.width = (rw - 1) + "px";            this.dragLen.style.height = "0px";            this.dragBox.style.height = this.btnWidth + "px";        } else if(this.option.scrollType == "H") {            this.priorBtn.style.width = this.btnWidth + "px";            this.setStyle(this.priorBtn, "scrollPrior");            this.centerRect.style.width = (rw - 2 * this.btnWidth) + "px";            this.setStyle(this.centerRect, "scrollCell");            this.nextBtn.style.width = this.btnWidth + "px";            this.setStyle(this.nextBtn, "scrollNext");            this.dragTable.style.height = rh + "px";            this.dragLen.style.width = "0px";            this.dragBox.style.width = this.btnWidth + "px";        }        //設定捲動區域的樣式,及拖動按鈕的樣式,        this.setStyle(this.dragLen, "scrollCell");        this.setStyle(this.dragBox, "scrollDrag");        //設定滾動表格和拖動表格的樣式,        this.setStyle(this.scrollTable, "scrollBox");        this.setStyle(this.dragTable, "scrollBox");        //設定寬、高        this.scrollTable.style.width = rw + "px";        this.scrollTable.style.height = rh + "px";    },



.scrollBox {    border-collapse:collapse;    border-spacing:0px;padding:0px;}.scrollCell {    padding:0px;vertical-align:top;background-color:#eeeeee;}.scrollUp {    padding:0px;background-color:#ddeeff;border-Bottom:1px solid #C3D2E6;}.scrollDown {    padding:0px;background-color:#ddeeff;border-Top:1px solid #C3D2E6;}.scrollPrior {    padding:0px;background-color:#ddeeff;border-right:1px solid #C3D2E6;}.scrollNext {    padding:0px;background-color:#ddeeff;border-Left:1px solid #C3D2E6;}.scrollDrag {    padding:0px;background-color:#ddeeff;border:1px solid #C3D2E6;}



    /**     *跟據滾動資料,重新整理捲軸位置     */    refresh:function() {        //計算捲動區域外的數量        var sl = this.scrollCount - this.showCount;        //發生了變化才重新計算        if(sl != this.tmpCount) {            //計算總象素長度            var slpx = sl * this.stepLen;            //計算拖動框長度            var cenLen = this.option.scrollType == "V"?                this.centerRect.offsetHeight:this.centerRect.offsetWidth;            var dragBoxLen = cenLen - slpx;            //如果計算出來的拖動按鈕過短,則重新計算步長,保證按鈕不再縮短            if(dragBoxLen < this.dragBoxMinLen) {                dragBoxLen = this.dragBoxMinLen;                slpx = cenLen - dragBoxLen;                this.stepLen = slpx/(this.scrollCount - this.showCount);            } else {                this.stepLen = 2;            }            //設定拖動按鈕長度            if(this.option.scrollType == "V") {                this.dragBox.style.height = (dragBoxLen - 2) + "px";            } else if(this.option.scrollType == "H") {                this.dragBox.style.width = (dragBoxLen - 2) + "px";            }            //緩衝當前數量            this.tmpCount = sl;        }        //計算拖動框位置        var len = parseInt(this.scrollIndex * this.stepLen, 10);        if(len < 0) {            len = 0;        } else if(len > cenLen - dragBoxLen) {            len = cenLen - dragBoxLen        }        //設定位置值        if(this.option.scrollType == "V") {            this.dragLen.style.height = len + "px";        } else if(this.option.scrollType == "H") {            this.dragLen.style.width = len + "px";        }    },



    /**     *滑鼠按下事件     */    doMouseDown:function(ev) {        this.base(ev);        //記錄原滑鼠的按下位置        this.dragX = ev.clientX;        this.dragY = ev.clientY;        //記錄原按鈕的位置,        if(this.option.scrollType == "V") {            this.dragPosition = this.dragLen.offsetHeight;        } else if(this.option.scrollType == "H") {            this.dragPosition = this.dragLen.offsetWidth;        }        //標識按鈕狀態        this.mouseDown = true;    },    /**     *滑鼠彈起事件     */    doMouseUp:function(ev) {        this.base(ev);        //還原拖動狀態        this.dragState = false;        //取消長按效果        if(this.setInt != null) {            clearInterval(this.setInt);            this.setInt = null;        }        //標識按鈕狀態        this.mouseDown = false;    },



        /**         *滑鼠移動事件         */        doMouseMove:function(ev) {            if(this.dragState) {                var len = 0, dragBoxLen = 0, centerLen = 0;                //計算設定拖動按鈕的位置,                if(this.option.scrollType == "V") {                    dragBoxLen = this._domValue(this.dragBox.style.height);                    centerLen = this._domValue(this.centerRect.style.height);                    len = this.dragPosition + ev.clientY - this.dragY;                    if(len < 0) {                        len = 0;                    } else if(len > centerLen - dragBoxLen) {                        len = centerLen - dragBoxLen;                    }                    this.dragLen.style.height = len + "px";                } else if(this.option.scrollType == "H") {                    dragBoxLen = this._domValue(this.dragBox.style.width);                    centerLen = this._domValue(this.centerRect.style.width);                    len = this.dragPosition + ev.clientX - this.dragX;                    if(len < 0) {                        len = 0;                    } else if(len > centerLen - dragBoxLen) {                        len = centerLen - dragBoxLen - 2;                    }                    this.dragLen.style.width = len + "px";                }                //計算明細數量位置                var tmpScrollIndex = this.scrollIndex;                if(dragBoxLen < 1) {                    this.scrollIndex = 0;                } else if(len >= centerLen - dragBoxLen) {                    this.scrollIndex = this.scrollCount - this.showCount;                } else {                    this.scrollIndex = parseInt(len/this.stepLen, 10);                }                //執行滾動事件                if(typeof this.onScroll == "function") {                    try {                        this.onScroll(this.scrollIndex, this.scrollIndex - tmpScrollIndex);                    } catch(e) {                        this.logInfo("onScroll Error!" + e.message);                    }                }            }        },



        /**         * 向上滾動         */        scrollPrior:function() {            if(this.scrollIndex > 0) {                this.scrollIndex --;                if(typeof this.onScroll == "function") {                    this.onScroll(this.scrollIndex, -1);                }                this.refresh();            }        },         /**         * 向下滾動         */        scrollNext:function() {            if(this.scrollIndex < this.scrollCount - this.showCount) {                this.scrollIndex ++;                if(typeof this.onScroll == "function") {                    try {                        this.onScroll(this.scrollIndex, 1);                    } catch(e) {                        this.logInfo("onScroll Error!" + e.message);                    }                }                this.refresh();            }        },        /**         * 向上滾動翻頁         */        scrollPriorPage:function() {            var tmpIndex = this.scrollIndex;            this.scrollIndex += this.showCount;            if(this.scrollIndex > this.scrollCount - this.showCount) {                this.scrollIndex = this.scrollCount - this.showCount;            }            if(tmpIndex != this.scrollIndex) {                if(typeof this.onScroll == "function") {                    try {                        this.onScroll(this.scrollIndex, this.scrollIndex - tmpIndex);                    } catch(e) {                        this.logInfo("onScroll Error!" + e.message);                    }                }                this.refresh();            }        },        /**         * 向下滾動翻頁         */        scrollNextPage:function() {            var tmpIndex = this.scrollIndex;            this.scrollIndex -= this.showCount;            if(this.scrollIndex < 0) {                this.scrollIndex = 0;            }            if(tmpIndex != this.scrollIndex) {                if(typeof this.onScroll == "function") {                    try {                        this.onScroll(this.scrollIndex, this.scrollIndex - tmpIndex);                    } catch(e) {                        this.logInfo("onScroll Error!" + e.message);                    }                }                this.refresh();            }                },



        /**         *捲軸總數量         */        setScrollCount:function(value) {            this.scrollCount = value;        },        /**         *捲軸顯示數量         */        setShowCount:function(value) {            if(value >= this.scrollCount) {                this.showCount = this.scrollCount;                this.dragTable.style.display = "none";            } else {                this.showCount = value;                this.dragTable.style.display = "";            }        },        /**         *捲軸滾到第幾個位置         */        setScrollIndex:function(index) {            if(index < 0) {                index = 0;            } else if(index > this.scrollCount - this.showCount) {                index = this.scrollCount - this.showCount;            }            if(this.scrollIndex != index) {                var tmpIndex = this.scrollIndex;                this.scrollIndex = index;                if(typeof this.onScroll == "function") {                    try {                        this.onScroll(this.scrollIndex, this.scrollIndex - tmpIndex);                    } catch(e) {                        this.logInfo("onScroll Error!" + e.message);                    }                }            }                    },



/** * 設定高度. */setHeight:function(height) {    this.base(height);this.refreshBox();this.refresh();},/** * 設定寬度. */setWidth:function(width) {    this.base(width);this.refreshBox();this.refresh();}





  test    <script src="../script/common/init.js" type="text/javascript"></script>                      確定        取消                退出                                                              



/** * test.html頁面控制類 * 建立:qzz * 日期: 2014-05-01 */(function(undefined) {    /**     * 控制類     */         testControllor = Extend(pageControllor, {        //初始化頁面        initPage:function() {            //修改頁面上的控制項屬性,綁定事件            this.test2.onClick = function() {                alert("確定");            }            this.test2.setCaption("確定");            this.test2.setWidth(50);            this.test3.onClick = function() {                alert("取消");            }            this.test3.setCaption("取消");            this.test11.onClick = function() {                alert("退出");            }            this.test12.setScrollCount(50);            this.test12.setShowCount(10);            this.test12.setScrollIndex(17);            this.test12.refresh();                        this.test13.setScrollCount(100);            this.test13.setShowCount(10);            this.test13.setScrollIndex(17);            this.test13.setWidth(400);            //this.test13.refresh();        }    });})();/** * 頁面對象建立,且啟動 */thisWindow.onShow = function() {    var tc = new testControllor();    tc.initPage();}




if(this.dragTable == null) { this.dragTable = this.createElement("TABLE"); } //清除原有行列,結構變化的時候,會有已存在行, while(this.dragTable.rows.length > 0) { this.dragTable.deleteRow(0); } //插入行列 if(this.option.scrollType == "V" && this.scrollTable.rows.length != 3) { this.priorBtn = this.scrollTable.insertRow(0).insertCell(0); this.centerRect = this.scrollTable.insertRow(1).insertCell(0); this.nextBtn = this.scrollTable.insertRow(2).insertCell(0); this.dragLen = this.dragTable.insertRow(0).insertCell(0); this.dragBox = this.dragTable.insertRow(1).insertCell(0); this.centerRect.appendChild(this.dragTable); } else if(this.option.scrollType == "H" && this.scrollTable.rows.length != 1) { var tr = this.scrollTable.insertRow(0); this.priorBtn = tr.insertCell(0); this.centerRect = tr.insertCell(1); this.nextBtn = tr.insertCell(2); var tr1 = this.dragTable.insertRow(0); this.dragLen = tr1.insertCell(0); this.dragBox = tr1.insertCell(1); this.centerRect.appendChild(this.dragTable); } var _this = this; //拖動框滑鼠按下事件, 並列印標誌dragState,把控制項置為焦點 this.dragBox.onmousedown = function(ev) { //拖動狀態 _this.dragState = true; _this.focus = true; } //上一個按鈕滑鼠按下事件,這裡處理長按時的效果,採用順延強制的方式, //scrollPrior()函數,是後續定義的向上滾動一行的函數, this.setInt = null; this.priorBtn.onmousedown = function(ev) { _this.scrollPrior(); _this.mouseDown = true; setTimeout(function() { if(_this.mouseDown) { _this.setInt = setInterval(function() { _this.scrollPrior(); if(_this.scrollIndex == _this.scrollCount - _this.showCount) { clearInterval(_this.setInt); } }, 50);//setInterval } }, 500); //setTimeout } //下一個按鈕滑鼠按下事件,這裡處理長按時的效果,採用順延強制的方式, //scrollNext()函數,是後續定義的向下滾動一行的函數, this.nextBtn.onmousedown = function(ev) { _this.scrollNext(); _this.mouseDown = true; setTimeout(function() { if(_this.mouseDown) { _this.setInt = setInterval(function() { _this.scrollNext(); if(_this.scrollIndex == _this.scrollCount - _this.showCount) { clearInterval(_this.setInt); }; }, 50); //setInterval } }, 500); //setTimeout } //中間地區滑鼠按下事件, 控制向下、上翻頁, //scrollPriorPage, scrollNextPage是後繼定義的翻頁函數。 this.centerRect.onmousedown = function(ev) { var ev = ev || event; if(_this.dragState != true) { var dlen = 0, clen; //debugger; var rect = this.getBoundingClientRect(); if(_this.option.scrollType == "V") { dlen = _this.dragLen.offsetHeight; clen = ev.clientY - rect.top; } else if(_this.option.scrollType == "H") { dlen = _this.dragLen.offsetWidth; clen = ev.clientX - rect.left; } if(clen > dlen) { _this.scrollPriorPage(); } else { _this.scrollNextPage(); } } } //添加到win容器中 this.win.appendChild(this.scrollTable); //重新整理捲軸框, 該方法為後繼定義的函數,用於重新整理滾動的樣式及位置。 this.refreshBox(); },上邊我們只是繪製出捲軸的結構,需要進行樣式控制,下邊refreshBox函數就是用於控制捲軸的樣式及位置的,這上邊用到幾個樣式,在com.comStyle.css檔案中定義如下:完成以上結構後,只是完成了顯示的效果,因為我們這個捲軸是通過設定資料明細數量來設定滾動的,因此需要與象素進行轉換計算,以設定拖動按鈕的位置,下面我們添加一個重新整理函數,用於重新整理捲軸的長度、拖動按鈕的長度及位置,添加refresh函數,如下:下面我們實現 拖動的事件,首先要先在滑鼠按鍵的時候初始化一些屬性,再在滑鼠彈起的時候,還原一些屬性,這裡我能通過重寫doMouseDown,doMouseUp事件來實現,如下:下面為滑鼠移動事件,當拖動狀態dragState等於true時,跟據滑鼠的起始位置及當前位置計算滾動按鈕的移動距離,並計算相應的滾動明細位置scrollIndex,並且執行滾動事件onScroll綁定的事件,由於滾動事件屬於外來事件,這裡作異常捕獲處理。下面我們再定義上邊用到的上、下明細函數,及上、下翻頁函數,如下:接著,再定義幾個屬性的設定函數,如下:最後設定高度,寬度的函數,到此我們的全部控制項編寫完成,從上邊來看,有點長,但是這點長絕對值得,因為後續控制項,將會大大降低實現難度,這裡有個缺點,就是沒有給向上、下按鈕添加圖片,不過,如果需要只需要修改樣式檔案,把圖片加上即可,當然,我們寫了控制,那麼就要測試一下,下面我們寫幾行代碼,用來測試控制項的使用,首先在test.html檔案中添加兩個捲軸控制項的標籤,如下id=test12/13的兩個控制項:然後我們在頁面控制器中添加一些代碼,如此就可以開啟test.html頁面查看效果,下載源碼包查看請關注我的下一編,javascript控制項開發之清單控制項(1)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.