使用js实现一个简单的滚动条过程解析


Posted in Javascript onSeptember 10, 2019

当我们给元素加上 overflow: auto; 的时候,就会出现滚动条,然而浏览的不同,滚动条的样式大不一样,有些甚至非常丑。

于是就想着自己写一个滚动条,大概需要弄清楚一下这几个点:

1、滚动条 bar 是根据内容的多少,高度不一样的,这个需要动态的计算

2、滚动条 bar 的 top 位置 和 内容scrollTop 的关系。

思路:

使用嵌套的布局,如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
      *{
        padding: 0;
        margin: 0;
      }
      .wrap{
        width: 400px;
        height: 400px;
        border: 2px solid deeppink;
        margin: 0 auto;
        overflow: hidden;
        position: relative;
      }
      .box-middle{
        height: 100%;
        overflow: auto;
        width: 200%;
      }
      .box{
        width: 50%;
      }
      .bar{
        background: #000;
        width: 10px;
        position: absolute;
        top: 0;
        right: 0;
      }
      .s1{
        height: 400px;
        background: pink;
      }
      .s2{
        height: 400px;
        background: deeppink;
      }
      .s3{
        height: 400px;
        background: deepskyblue;
      }
    </style>
  </head>
  <body>
    <div class="wrap" id="wrap">
      <div class="box-middle" id="boxMidle">
        <div class="box" id="content">
          <div class="s1">内容1</div>
          <div class="s2">内容2</div>
          <div class="s3">内容3</div>
        </div>
      </div>
      <div class="bar" id="bar"></div>
    </div>
     
  </body>
</html>

wrap 为最外层,给overflow:hidden;。

box-middle 是中间层,也是有滚动条的一层,可以宽度给多一点,这样就看不见滚动条了。

box就是内容层,通过js,计算使得 box 的宽度和wrap 保持一致,这样就完全看不见滚动条了

bar 为滚动条

写js之前,首先要弄懂一下三个属性:

offsetHeight : height + padding + border
clientHeight : height + padding
scrollHeight : 内容的高度(所有子元素高度和) + padding

1、计算比例:

bar的高度 / wrap的高度 = wrap的高度 / wrap 内容部子元素的高度和 ; 此时忽略 wrap 的padding:0

bar的top / wrap的scrollTop = wrap的高度 / wrap 内容部子元素的高度和 ;

需要注意,当比例 的 值 小于 1 的时候,说明 这个时候没有出现滚动条。

知道算法之后,写代码就简单很多,普通版代码如下:

var $wrap = document.getElementById("wrap");
var $boxMidle = document.getElementById("boxMidle");
var $content = document.getElementById("content");
var $bar = document.getElementById("bar");
$content.style.width = $wrap.clientWidth + "px"; //内容的宽度
var rate = $boxMidle.clientHeight/ $boxMidle.scrollHeight; //滚动条高度的比例,也是滚动条top位置的比例
 var barHeight = rate * $boxMidle.clientHeight; //滚动条的 bar 的高度
if(rate < 1){
  //需要出现滚动条,并计算滚动条的高度
  $bar.style.height = barHeight + "px";
}else{
  //不需要出现滚动条
  $bar.style.display = "none";
}
$boxMidle.onscroll = function(e){
  console.log("offsetHeight"+this.offsetHeight); //height + padding + border
  console.log("clientHeight"+this.clientHeight); // height + padding
  console.log("scrollHeight"+this.scrollHeight); //内容的高度(所有子元素高度和) + padding
  console.log(this.scrollTop);
  $bar.style.top = this.scrollTop*rate + "px";
}

使用面向对象版:

function ScrollBar(opt){
  var me = this;
  me.$wrap = document.getElementById(opt.wrap);
  me.$boxMidle = document.getElementById(opt.boxMidle);
  me.$content = document.getElementById(opt.content);
  me.$bar = document.getElementById(opt.bar);
  me.init();
  me.$boxMidle.onscroll = function(e){
    //console.log("offsetHeight"+this.offsetHeight); //content + padding + border
    //console.log("clientHeight"+this.clientHeight); // content + padding
    //console.log("scrollHeight"+this.scrollHeight); //内容的高度 + padding
    console.log(this.scrollTop);
    me.scrollToY(this.scrollTop * me.rate)
  }
}
ScrollBar.prototype.init = function(){
  this.$content.style.width = this.$wrap.clientWidth + "px"; //内容的宽度
  this.rate = this.$boxMidle.clientHeight/this.$boxMidle.scrollHeight; //滚动条高度的比例,也是滚动条top位置的比例
   this.barHeight = this.rate * this.$boxMidle.clientHeight; //滚动条的 bar 的高度
  if(this.rate < 1){
    //需要出现滚动条,并计算滚动条的高度
    this.$bar.style.height = this.barHeight + "px";
  }else{
    //不需要出现滚动条
    this.$bar.style.display = "none";
  }
}
ScrollBar.prototype.scrollToY = function(y){
  if(this.rate < 1){
    this.$bar.style.top = y + 'px';
  }
}
 
var obj = new ScrollBar({"wrap":"wrap","boxMidle":"boxMidle","content":"content","bar":"bar"});

最后看一下效果:

虽然效果很丑,但是可控,自己调一下就可以了

使用js实现一个简单的滚动条过程解析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript同步Import,同步调用外部js的方法
Jul 08 Javascript
给html超链接设置事件不使用href来完成跳
Apr 20 Javascript
深入讲解AngularJS中的自定义指令的使用
Jun 18 Javascript
对象题目的一个坑 理解Javascript对象
Dec 22 Javascript
浅析AngularJS中的指令
Mar 20 Javascript
JS模仿腾讯图片站的图片翻页按钮效果完整实例
Jun 21 Javascript
javascript实现右下角广告框效果
Feb 01 Javascript
js和jquery中获取非行间样式
May 05 jQuery
详解基于node的前端项目编译时内存溢出问题
Aug 01 Javascript
详解Vue用自定义指令完成一个下拉菜单(select组件)
Oct 31 Javascript
mpvue实现左侧导航与右侧内容的联动
Oct 21 Javascript
jquery实现轮播图特效
Apr 12 jQuery
html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】
Sep 10 #jQuery
Elasticsearch实现复合查询高亮结果功能
Sep 10 #Javascript
如何通过shell脚本自动生成vue文件详解
Sep 10 #Javascript
js获取 gif 的帧数的代码实例
Sep 10 #Javascript
微信小程序实现pdf、word等格式文件上传的方法
Sep 10 #Javascript
js中console在一行内打印字符串和对象的方法
Sep 10 #Javascript
layui表格内放置图片,并点击放大的实例
Sep 10 #Javascript
You might like
Discuz! Passport 通行证整合
2008/03/27 PHP
PHP中单例模式与工厂模式详解
2017/02/17 PHP
关于IE、Firefox、Opera页面呈现异同 写脚本很痛苦
2009/08/28 Javascript
js 蒙版进度条(结合图片)
2010/03/10 Javascript
Jquery弹出窗口插件 LeanModal的使用方法
2012/03/10 Javascript
ECMAScript 6即将带给我们新的数组操作方法前瞻
2015/01/06 Javascript
TypeScript具有的几个不同特质
2015/04/07 Javascript
JS阻止事件冒泡行为和闭包的方法
2016/06/16 Javascript
jQuery和hwSlider实现内容响应式可触控滑动切换效果附源码下载(二)
2016/06/22 Javascript
JS实现六位字符密码输入器功能
2016/08/19 Javascript
JavaScript中浅讲ajax图文详解
2016/11/11 Javascript
Vue from-validate 表单验证的示例代码
2017/09/26 Javascript
js遍历添加栏目类添加css 再点击其它删除css【推荐】
2018/06/12 Javascript
JavaScript学习教程之cookie与webstorage
2019/06/23 Javascript
layer.open回调获取弹出层参数的实现方法
2019/09/10 Javascript
解决echarts数据二次渲染不成功的问题
2020/07/20 Javascript
vue实现下拉菜单树
2020/10/22 Javascript
vue 中的动态传参和query传参操作
2020/11/09 Javascript
Python ljust rjust center输出
2008/09/06 Python
python在linux系统下获取系统内存使用情况的方法
2015/05/11 Python
Python常用的文件及文件路径、目录操作方法汇总介绍
2015/05/21 Python
Python2中的raw_input() 与 input()
2015/06/12 Python
python+selenium 定位到元素,无法点击的解决方法
2019/01/30 Python
python 列表输出重复值以及对应的角标方法
2019/06/11 Python
Python使用pycharm导入pymysql教程
2020/09/16 Python
python 5个实用的技巧
2020/09/27 Python
淘宝活动策划方案
2014/02/06 职场文书
《路旁的橡树》教学反思
2014/04/07 职场文书
西柏坡导游词
2015/02/05 职场文书
北京天坛导游词
2015/02/12 职场文书
当幸福来敲门英文观后感
2015/06/01 职场文书
完美处理python与anaconda环境变量的冲突问题
2021/04/07 Python
Vue Element-ui表单校验规则实现
2021/07/09 Vue.js
DIV CSS实现网页背景半透明效果
2021/12/06 HTML / CSS
MySQL创建表操作命令分享
2022/03/25 MySQL
《王者天下》第4季首话新剧照 4月9日正式开播
2022/04/07 日漫