定制自己的导航条
一、滚动条的应用场景
滚动条–我们在上网过程中遇到最普遍的东西,在我们的眼中这是浏览器与生具有的,不需要编码者去担心怎么实现。
在html + css + js的web开发中,给一个div设定固定的尺寸,当内部内容超过这个容器的时候滚动条自然的就能出现(借助overflow属性)。
在flash编程中,纯as3没有这么一个功能说给定一个大小,当内容超过容器的时候会自动出现滚动条,但我们也能通过在嵌入swf的外层容器上设定大小,这样当swf这个flash超过容器大小的时候也会出现滚动条,但这个滚动条是浏览器的,并非flash!
总的来说,滚动条的作用在于:在有限的空间尽量多的展示更多的内容,让某一类的内容显示在一起。举个最简单的例子,QQ的聊天界面、浏览器……
二、具备显示滚动条的场景
组成: 内容可显示区域、内容容器、滚动条外部容器、滚动条可拖动部分;这是会出现滚动条的几个最基本元素。
如下图所示:
整个过程中需要用到的数据有:
内容可见区域:h
内容容器高度(及所有内容的所有高度): H
滚动条外部容器(这里讨论和内容可见区域相等):a
滚动条可拖动部分高度:b
三、实现步骤(事件驱动)
从头开始分析(目的实现一个和QQ聊天界面类似的功能):
1.第一条消息到达,添加到H中,注意并不是h中,h和H的关系是:
H.mask = h // as3
// html
<div style="overflow: hidden;"> <!--h-->
<div style="position:absolute;"></div> <!--H-->
</div>
现在H的高度是第一条信息的高度,判断:
if (H > h) {
// 出现滚动条,并向上移动容器H的y值直道H的底部与h对齐
} else {
// 未达到滚动条出现的要求,持续上面的步骤
}
2.接下来是响应用户的各种鼠标事件:
1.滚动条的拖动事件
需要监听鼠标的按下状态和鼠标的移动状态以及鼠标抬起事件;
// b上需要绑定的事件有mousedown
b.addEventListener("mousedown", function() {}); // js
b.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void {}); // as3
// stage或者document上需要绑定mousemove 和 mouseup事件
document.addEventListener("mousemove", function() {});
document.addEventListener("mouseup", function() {});
stage.addEventListener(MouseEvent.MOUSE_MOVE, function(e:MouseEvent):void {});
stage.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void {});
2.鼠标在内容可视区域的滚轮事件
h.addEventListener("mousewheel DOMMouseScroll", function() {});
h.addEventListener(MouseEvent.MOUSE_WHEEL, function(e:MouseEvent):void {});
3.以上事件发生之后,滚动条可滚动部分和内容容器的位置同步,以及防越界问题!
四、代码实现
由于监听了鼠标的移动事件,因此需要保证是在滚动条可拖动部分按下过后才能响应移动事件,并且在拖动过程中需要记录拖动的前一个y轴位置。
/*
* js实现导航条过程,as算法类似
*/
var isMouseDown = false; // 判断鼠标是否出于按下状态
var tmpY; // 记录拖动的前一个位置属性
b.addEventListener("mousedown", function(e) {
e.stopPropagation();
isMouseDown = true;
tmpY = e.clientY;
});
// 在捕获阶段响应事件更流畅
document.addEventListener("mousemove", function(e) {
e.stopPropagation();
var _diffY = e.clientY - tmpY; // 计算得到拖动的距离
// 计算滚动条移动的终点
_diffY += b.style.top.replace("px", "") * 1;
// 必须在按下状态才能响应移动事件
if (isMouseDown) {
changePosition(_diffY);
}
// 更新tmpY
tmpY = e.clientY;
}, true);
document.addEventListener("mouseup", function(e) {
isMouseDown = false;
});
// 监听此事件避免拖动过程中选中网页中的文字
document.onselectstart = function() {
return !isMouseDown;
}
h.addEventListener("mousewheel", function(e) {
var _diff = (e.originalEvent.wheelDelta > 0) ? 30 : - 30, // 滚动一次移动的距离
_top = b.style.top.replace("px", "") * 1;
_diff = _top + _diff;
changePosition(_diff);
});
function changePosition(dest) {
var H, // 内容容器的高度
h, // 可视区域高度,常量
_nextTop; // 内容容器的目标位置
if (dest < 0)
dest = 0;
if (dest > h - b)
dest = h - b;
_nextTop = -(H - h) * dest / (h - b);
// 同步改变滚动条位置和内容容器位置
H.style.top = _nextTop + "px";
b.style.top = dest + "px";
}
当然, 还需要有个动态改变滚动条高度的函数,就是在有消息不断添加到容器里面的时候触发的:
// 根据消息容器的大小计算出滚动条的高度
function changeScrollbarLen() {
var H,
_barLen = h * h / H; // 就一个数学公式计算出滚动条对应的高度
a.style.display = "block"; // 证明该显示滚动条了
b.style.height = _barLen + "px";
// 可以做一个动画效果,模拟消息被从下往上推上去
}
- 上一篇:Node.js中的TCP套接字编程
- 下一篇:理解node.js的单线程