首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >随心所欲的滚动条,远离产品汪(一)

随心所欲的滚动条,远离产品汪(一)

作者头像
HTML5学堂
发布2018-03-13 15:21:25
1.5K0
发布2018-03-13 15:21:25
举报
文章被收录于专栏:HTML5学堂HTML5学堂
在我们的开发生活中,相信很多人都会遇到形形色色的项目需求,比如更改浏览器的默认样式,在产品定下需求后给的网页设计图中我们最常遇到的是自定义滚动条的样式,或者当你想构建一个很有特色和创意的网页,那么也肯定希望自己能够去设置滚动条样式,当然,做好准备才是最重要的,最近在项目中遇到了,正好来总结一下。

本文主要内容

1.基本原理图

2.结构布局分析

3.功能实现逻辑

4.实现步骤

5.小结

1.基本原理图

大家可以先根据原理图自己分析一波,有利于加深对下文的理解

2. 结构布局分析

我们在开发项目中会时不时的碰到这种情况,当滚动块B超出了父级可视部分,我们总会设置overflow的属性值来隐藏超出的部分,根据默认的滚动条来操作隐藏区的内容,当将可视区A设置overflow:auto时,网页会显示出默认的滚动条样式。

如图下所示,初始滚动条的效果:

此时我们会发现,有些时候设计师给出的设计图滚动条的样式是不同的或者默认的滚动条样式会影响到我们对网页的整体感觉,所以我们需要隐藏默认滚动条,将可视区设置为overflow:hidden,自己去重新设置滚动条的样式。

首先根据原理图,我们写出基本结构代码:

<body>
   <div class="wrap">
      <div class="con" id = "bx">//可视区A
         <p id="cn"> //滚动块B
            滚动块B内容
          </p>  
       </div>
       <div class="boxscr" id = "bs">//滚动条滚动区
          <div class="scr" id = "sc"></div> //滚动条
       </div>
    </div>
</body>

根据滚动条的上下滚动方式,我们可以想到可以通过控制margin-top和top的值来实现滚动条的滚动,本文中通过使用定位的方式来实现。

接下来我们完善具体的样式结构:

<!DOCTYPE html>
<html>
    <head>
        <title>自定义滚动条</title>
        <meta charset="utf-8">
        <style type="text/css">
.wrap {
            width: 200px;
            height: 150px;
            margin: 0 auto;
        }
        .con {
            float: left;
            overflow: auto;
            width: 180px;
            height: 150px;
            background: #39f;
        }
        .con p {
            margin: 0;
            color: #fff;
            text-align: center;
            line-height: 20px;
            font-size: 14px;
        }
        .boxscr {
            float: right;
            position: relative;
            width: 20px;
            height: 150px;
            background: #d9ecff;
        }
        .scr {
            position: absolute;
            width: 20px;
            border-radius: 10px;
            background: #c6ccff;
            cursor: pointer;
        }
    </style>
    </head>
    <body>
        <div class="wrap">
            <div class="con" id = "bx">
                <p id="cn">
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                    HTML5学堂-自定义滚动条
                </p>  
            </div>
            <div class="boxscr" id = "bs">
                <div class="scr" id = "sc"></div>
            </div>
        </div>
    </body>
</html>

实现的效果:

ps:当前的效果样式只是个示例,大家可以根据自己的实际需求进行样式调整。

3. 功能实现逻辑

1. 通过控制滚动条的top值来实现滚动条的上下滚动,但是滚动块的内容有限,滚动条不可能无限滚动,所以滚动条有着自己的滚动范围。

2. 同理,滚动块B则通过可视区A的scrollTop来控制上下滚动,当然也有着自己的滚动范围。

3. 如何将两者关联起来呢,实际上细心的你已经发现:滚动条C的高度/滚动区D的高度 = 可视区A的高度/ 滚动块B的高度,即滚动块的滚动距离和滚动条的滚动距离它们的比都是存在联系的。

现在我们分几个步骤来实现它们。

4. 实现步骤

此处我们先上代码,然后根据代码来进行具体分析:

<script>
    var bx = document.getElementById("bx"),
        cn = document.getElementById("cn"),
        bs = document.getElementById("bs"),
        sc = document.getElementById("sc"),


        oldY = 0,      //鼠标初次点击的Y轴坐标
        newY = 0,      // 鼠标拖动时的Y轴坐标
        nowY = 0,      // 鼠标拖动时滚动条C距父级顶部的高度
        maxY = 0,      // 拖动的最大极限值
        nowDisY = 0,   // 点击滚动条C时距父级顶部的高度


        bxHeight = bx.clientHeight,  // 可视区A高度
        bsHeight = bs.clientHeight, //  滚动区D高度
        cnHeight = cn.offsetHeight;  // 滚动块B的高度


        // 根据滚动块B实际内容高度控制滚动条C的高度
        scHeight = bxHeight/cnHeight * bxHeight;
        sc.style.height = scHeight + "px";  


        // 当滚动块B实际高度小于可视区时,滚动条隐藏
        if (cnHeight < bxHeight) {
            bs.style.display = "none";
        };


        sc.onmousedown = function(e) {
            oldY = e.clientY;
            nowDisY = sc.offsetTop;         // 当前的滚动条C的top值
            e.preventDefault();
            document.onmousemove = function(e) {
                newY = e.clientY;
                nowY = nowDisY + newY - oldY;  // 拖动后的滚动条C的top值
                maxY = bsHeight - scHeight;    // 设置滚动条top极限值


                if (nowY <= 0) {
                    nowY = 0;
                };
                if (nowY >= maxY) {
                    nowY = maxY;
                };


            bx.scrollTop = nowY/maxY * (cnHeight - bxHeight);  // 设置滚动块B的scrollTop值
            sc.style.top = nowY + "px";
            }
        }
        document.onmouseup = function() {
            document.onmousemove = null;   
        }
</script>

a) 计算滚动条高度

因为滚动条C的高度不是一成不变的,需要滚动块B的实际高度与可视区A高的相似比来计算。

即:滚动块B的高/可视区A的高 = 滚动区D的高/滚动条C的高

scHeight = bxHeight/cnHeight * bxHeight;// 根据滚动块B实际内容高度控制滚动条C的高度
sc.style.height = scHeight + "px";  

b) 鼠标拖动时的坐标位置

无论开始鼠标点击滚动条哪一个位置,都将视为点击滚动条的顶点坐标。

即:滚动条的滚动距离 = 拖动后鼠标变化的Y值 – 点击时鼠标获取的Y值

nowY = nowDisY + newY - oldY;  // 拖动后的滚动条C的top值

c) 实现滚动条拖动

在实现滚动条拖动的同时,我们并不能忽视滚动条的当前位置,当二次拖动时,此时的滚动条或许已经偏离了初始位置。

即: 当前滚动条位置的top值 = 拖动后鼠标变化的Y值 – 点击时鼠标获取的Y值 + 初始滚动条的top值

nowY = nowDisY + newY - oldY;  // 拖动后的滚动条C的top值

d) 限制滚动条的拖动范围

滚动条有着自己的活动范围,即滚动条的top值有着自己的极限距离,当超过了极限距离,此时的top值就一直等于这个值,反之最小值也是如此,那么这个值是多少呢?

由原理图可知:0 <= 滚动条的top值 <= 滚动区D的高度 – 滚动条C的高度

maxY = bsHeight - scHeight;    // 设置滚动条top极限值
if (nowY <= 0) {
   nowY = 0;
};
if (nowY >= maxY) {
   nowY = maxY;
};

e) 所有东西都准备好了,怎么让滚动条C的滚动控制到滚动块B呢

首先我们需要知道,滚动块B可滚动的极限值,即可视区A的高 – 滚动块B的高。 滚动块B的滚动距离与滚动条C的滚动距离相呼应。

即: 可视区A的scrollTop = 顶点可移动极限值 * 滚动条滚动的比值

bx.scrollTop = nowY/maxY * (cnHeight - bxHeight);  // 设置滚动块B的scrollTop值
sc.style.top = nowY + "px";

这个时候,刷新下网页,就可以发现滚动条已经可以滚动了,同时也控制着内容区的滑动。

5.小结

自定义滚动条是基于拖拽的原理实现的,在学堂官网中,大家可以找到“拖拽”的相关知识去进一步巩固了解,回到当前,大家有没有发现还存在一些不好的地方呢?

1. 每次滚动都需要拖拽,很累啊,为什么鼠标滚轮不能用?

2. 并没有到考虑兼容问题。

由于篇幅原因,这里不再进行说明,将在下周同一时间更新自定义滚动条的续篇,着重为大家介绍滚轮事件的添加及兼容问题的解决。

本文系HTML5学堂独家内容,转载请在文章开头显眼处注明作者和出处“HTML5学堂(http://www.h5course.com/)”

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 懂点君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.基本原理图
  • 大家可以先根据原理图自己分析一波,有利于加深对下文的理解
  • 2. 结构布局分析
  • 4. 实现步骤
    • a) 计算滚动条高度
      • b) 鼠标拖动时的坐标位置
        • c) 实现滚动条拖动
          • d) 限制滚动条的拖动范围
            • e) 所有东西都准备好了,怎么让滚动条C的滚动控制到滚动块B呢
            • 这个时候,刷新下网页,就可以发现滚动条已经可以滚动了,同时也控制着内容区的滑动。
            • 5.小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档