最近自建Javascript库已日渐完善,在基础库的基础上,增加很多自制UI控件,除了之前展示的Grid,最近还完成了Tab,Accordion,Tree,DropDrag,DigitalNumber,以及矢量数字时钟等控件,本来想以文章的形式给大家分享这些控件代码,但是每个控件代码量都在200行以上,看来放上来是个不切合实际的事情。

今天主要想给大家分享的仅仅是Tab控件中的一个功能:如何实现可活动标题。这个功能的大致需求是,当Tab标题栏中 Tab页总宽度大于标题栏实际可见宽度后,超出的Tab页会被覆盖在标题栏的内层,同时两侧各增加一个半透明的Button,点击可使标题栏内部左右滑动。

Tab标题栏的Html组织结构如下:

Css结构不具体说明,只指明几个关键点:外层Div必须是 overflow:hidden;position:relative; 内层ul元素必须是 position:absolute;width:xxxxxpx。这里表示宽度足够长,这样当ul内部Tab页标题增多时,能形成一个内部遮挡的效果,两侧的 i 元素是左右滑动按钮。设置ul 的style.left即可控制它在外层div中的相对位置,设负值就向左侧移动,正值就往右侧移动。效果如下图:

下面就是javascript代码需要实现的逻辑,在每次增加新标题时,计算ul内元素总宽度,超过外层div宽度时,则生成两个dom元素,作为控制左右滑动的按钮,滑动效果使用了计时器函数,我的大致设计思路是这样的,为每个button注册一个"mousedown"事件,启动一个计时器,不断地改变ul的style.left数值。另外注册一个"mouseup"事件,关闭这个计时器听着移动。

计时器使用 setIterval,我采用了之前介绍的我类库中封装的 Function.createInterval 原型方法。代码如下:

moveLeft : function(){
  var left
= this.ul.offsetLeft,
    style
= this.ul.style;
  if(left + 4 <= 0){
    style.left
= left + 4 + 'px';
  }
else {
    style.left
= '0px';
  }
},
moveRight : function(){
  var left
= this.ul.offsetLeft,
    style
= this.ul.style;
  if(this.ulWidth + left -4 >= this.ulcw - 20){
    style.left
= left - 4 + 'px';
  }
else {
    style.left
= this.ulcw - this.ulWidth - 20 + 'px';
  }
}, 

HL.on(left,
'mousedown', function(){
  movingTask
= this.moveLeft.createInterval(25, this);
  movingTask.run();
},
this);
HL.on(left, 'mouseup', function(){
  movingTask.stop();
},
this);
HL.on(right, 'mousedown', function(){
  movingTask
= this.moveRight.createInterval(25, this);
  movingTask.run();
},
this);
HL.on(right, 'mouseup', function(){
  movingTask.stop();
},
this);

其中ulWidth 是ul内部元素总宽度,ulcw是外层div的可见宽度,这两个值会在每次触发 addtab 事件后缓存在原型变量中(Tab UI类也实现了 观察者模式接口),movingTask是一个闭包私有变量,控制滑动任务。

moveLeft 与 moveRight 函数作用是改变ul的left数值,并且对移动范围进行控制,具体逻辑你们看代码自己理解吧。

代码中还有很多前提条件没有写,关于标题左右滑动功能,这样基本可以实现,当然还要删除标题时,对坐标的一个恢复等等逻辑没有介绍,其实做UI还是蛮有意思的,实现各种各样复杂多变的动态效果,今天刚看了下《愤怒小鸟》的网页canvas版本,叹为观止,绝对今天开始强化学习下,OK今天先到这里