javascript控件开发之滚动条控件

首先,基于行前几篇开发的的框架,我们在目录 component\ui\下添加文件 com.ui.scrollBar.js, 在文件中定义com.ui.scrollBar类,继承com.ui.window类,如下

/** * 滚动条控件. * 创建: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; },

定义好基本的属性后,开始绘制滚动条的框架, 这里我们采用来实现, 比如纵向滚动条,则生成一个三行一列的,第一行与第三行用作上下按钮,中间用作滚动区域,(横向的同理),

然后在滚动区域(上边的第二行)中又加入一个两行一列的,用作中间拖动按钮,第一行,绘制边线与背景相同,第二行绘制成按钮,通过调整第一行的行高来设定按钮的位置,

绘制完成后,添加按钮的事件,及拖动事件, 如下:

/** * 渲染. */ render:function() { this.base(); //创建滚动条结构 if(this.scrollTable == null) { this.scrollTable = this.createElement("TABLE"); } //清除原有的行列,结构变化的时候,会有已存在行 while(this.scrollTable.rows.length > 0) { this.scrollTable.deleteRow(0); } //创建拖动按钮结构 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函数就是用于控制滚动条的样式及位置的,

/** * 刷新布局 */ 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"; },

这上边用到几个样式,在com.comStyle.css文件中定义如下:

.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函数,如下:

/** *跟据滚动数据,刷新滚动条位置 */ 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 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"; } },