嘛,最近 Chrome 升级了. 不知道大家有没有发现, 我是今天刚升级的, 开始还蛮不适应, 以为开了什么特别的模式.
不过 Chrome 倒是把 Mobile 模拟放到了一个更方便地方(debug输出区标签).
除此之外,就是 scrollbar 进行的大变更, 更像移动端的设计了~ 可喜可贺.多少年了,那个占了20px的滚动条终于消失了!

scrollbar

看! 右侧那个小小的滚动条,和wordpress的感觉更融合了,好棒!! google给你1024个赞~~
那好,趁着这次机会,我就翻出我那个厚厚的小笔记,分享一下scrollbar的设计与实现吧…


下面,先让我们分析一下scrollbar的设计规则:

scrollbar_name_define

上图简单的定义了一些我们名词,在下面的说明及代码中都以此为根据.

  1. 首先,让我们的scrollbar的长度应该与所显示的pane一致. 即: pane.height = scrollBar.height.(当然,这里我们忽略了border,padding等数据,但实际中这些都要考虑在内.)
  2. 滑块手柄scrollBar.handle的长度,取决于pane与content高度的比例. 即: scrollBar.handle.height = pane.height * (pane.height / content.height).(当然,handle也可以固定一个高度,但这里所指的是标准设计下)
  3. 于此同时,整个滑块可移动的范围缩减为: scrollBar.range.height – scrollBar.handle.height. 该值对应的是content所能滚动的最大值:content.height – pane.height
  4. 当handle向下滑动距离x时, content应该滑动多少呢 : x / (scrollBar.range.height – scrollBar.handle.height) = y / (content.height – pane.height)

废话了好多..下面让我们做演示好了.

 样式表


#_demo .pane{ width:200px; height:200px; position:relative; border:#FAFAFA solid 10px; font-size:14px; overflow:hidden; }
#_demo .pane .content{ position:relative; margin-right:20px; text-align:center; }
#_demo .pane .scrollBar{ position:absolute; right:0px; width:16px; height:200px; background:#FDE1DB; border-radius:4px; }
#_demo .pane .scrollBar .handle{ position:absolute; display:block; background:#F58E78; top:0px; width:10px; height:20px; margin:0px 3px; border-radius:3px; cursor:pointer; }
#_demo .pane .scrollBar .handle:hover{ background:#F26C4F; }

 正文


<div id="_demo">
    <div class="pane">
        <div class="scrollBar"><a href="javascript:;" class="handle"></a></div>
        <div class="content">
            嘛..这里是演示..<br />
            1<br />
            2<br />
            3<br />
            ...
        </div>
    <div>
</div>

 代码


// 点击时,开启拖拽状态. 并记录鼠标与handle的相对位置
$("#_demo .handle").mousedown(function(event) {
    var self = $(this);
    self.data("_drag", 1);
    self.data("_offset", self.offset());
    self.data("_mouseY", event.pageY);
});
// 检测当前位置
var checkPos = function(dom, _y){
    var self = $(dom);

    var pos_top = self.position().top;
    if(pos_top <= 0 &amp;&amp; (_y === undefined || _y < 0)) {
        self.css("top", 0);
        return false;
    }

    var maxTop = $(".scrollBar").height() - self.height();
    if(pos_top >= maxTop &amp;&amp; (_y === undefined || _y > 0)) {
        self.css("top", maxTop);
        return false;
    }
    return true;
}
// 释放时,关闭拖拽状态
$("#_demo .handle").mouseup(function() {
    $(this).data("_drag", 0);
    checkPos(this);
});
// 移除时,关闭拖拽状态
$("#_demo .handle").mouseout(function() {
    $(this).data("_drag", 0);
    checkPos(this);
});
// 鼠标开始移动
$("#_demo .handle").mousemove(function(event) {
    var self = $(this);
    if (self.data("_drag") == 1) {
        var old_offset = self.data("_offset");
        var mousemoveY = event.pageY - self.data("_mouseY");
        var top = old_offset.top + mousemoveY;

        if (!checkPos(this, mousemoveY)) return;

        // 取值
        var contentH = $(".content").height();
        var paneH = $(".pane").height();
        var handleH = $(".handle").height();
        var rangeH = $(".scrollBar").height() - handleH;

        // 移动
        self.offset({top:top, left:old_offset.left});
        var pos_top = $(".handle").position().top;
        if (pos_top <= 0) pos_top = 0;
        else if(pos_top >= rangeH) pos_top = rangeH;
        var content_top =  pos_top * (contentH - paneH) / (rangeH - handleH);
        $(".content").css("top", content_top);

        // 更新数据
        self.data("_offset", self.offset());
        self.data("_mouseY", event.pageY);
    }
});
// 初始化
$(function(){
    $("#_demo .handle").height($(".pane").height() * $(".pane").height() / $(".content").height());
});

嘛,这里展示的只是最简单的的一种拖拽实现方式, 效率并不高, 泛用性也不高.但是毕竟容易解释.
如果提高效率和功能的话,应该用addListener去做事件监听,就不一一累牍了.

推荐一个做的很棒的Jquery scroller插件
http://manos.malihu.gr/tuts/custom-scrollbar-plugin/complete_examples.html