没事找事,明明overflow:scroll|auto就可以,只是难看点(实际上css也能设置)。只当练习写拖拽、监听事件、位置检测了。

原理是对滑动条块进行监听,按下鼠标按键后,监听鼠标移动,然后根据滑动条块移动的百分比算出滚动区域的滚动程度,用marginLeft进行滚动。具体的写在注释里。

整体弄成了一个对象,防止各种乱七八糟的数据污染全局变量。另外,对象内部调用的函数也都写到了对象构造函数的里面,由于对象作用域链的原理,外部无法进行调用,防止不小心在外部调用。

 <!DOCTYPE html>
<html>
<head>
<title>A demo</title>
<meta http-equiv="content-type" name="author" content="Fujihara No Kokukiyo" />
<meta charset="utf-8" />
</head>
<style rel="stylesheet" type="text/css">
.outer{width:500px;border:1px solid black;overflow:hidden;margin:50px 0 0 100px;}
.test_div{width:1200px;background-image:linear-gradient(90deg,lightcoral 0%,lightgreen 50%,lightblue 100%);height:150px;}
.slider_bar,.slider_block{ border-radius:5px;}
.slider_bar{position:relative;width:80%;margin:5px auto 5px auto;background-color:lightgreen;height:5px;}
.slider_block{width:20px;height:5px;background-color:grey;cursor:pointer;position:absolute;}
</style>
<script type="text/javascript">
window.onload=function(){
/**
* 滑动条对象构造函数,
* 内含其他功能性函数,利用函数作用域链的原理,防止自己随意调用
* 兼容:firefox、opera、chrome
* ie没试,然而显然不兼容旧版本ie(8及之前),因为旧版本ie添加事件监听函数的方法不同。如若要兼容ie,还需要添加其他函数
* js生成的滑动条类名为slider_bar、滑动块类型为slider_block,可用css样式自己设置大小、颜色等。
* 滑动条左右padding未限制滑动条界限,如若需要限制,须在计算部分进行细小修改,加算padding,此处略去。
*
* @param {DOMElement} slider_content 被滚动的元素(不是被滚动元素的父元素)
*/
function Slider(slider_content){
//slider_instance为对象本身(在事件处理函数中会进行访问,而事件处理函数中的this对象已被注入为event.currentTarget,因此预先存储)
var slider_instance=this;
//this.slider_content为被滚动的元素
this.slider_content=slider_content;
//this.outer为被滚动元素的父元素
this.outer=slider_content.parentNode;
//创建滑动条
this.slider_bar=createSliderBar();
//创建滑动条块
this.slider_block=createSliderBlock();
//拼装
this.slider_bar.appendChild(this.slider_block);
this.outer.appendChild(this.slider_bar);
//被滚动元素可被滚动的总宽度
this.slider_content_width=this.slider_content.offsetWidth-this.outer.clientWidth;
//滑动条块可滑动的总宽度
this.slider_bar_width=this.slider_bar.clientWidth-this.slider_block.offsetWidth;
//被滚动元素的左边距(相对父元素)
this.slider_content_left=0;
//滚动块的左边距(相对父元素)
this.slider_block_left=0;
//滑动条的左边距(相对视口)
this.slider_bar_pageLeft=getPageLeft(this.slider_bar);
//滑动条块添加鼠标压键事件
this.slider_block.addEventListener("mousedown",mousedownHandler,false);
//离开父元素后取消鼠标移动事件
this.outer.addEventListener("mouseleave",mouseupHandler,false);
//鼠标弹键时取消鼠标移动事件
this.outer.addEventListener("mouseup",mouseupHandler,false);
/**
* 创建滑动条
*/
function createSliderBar(){
var slider_bar=document.createElement("div");
slider_bar.className="slider_bar";
return slider_bar;
}
/**
* 创建滑动条块
*/
function createSliderBlock(){
var slider_block=document.createElement("div");
slider_block.className="slider_block";
return slider_block
}
/**
* 鼠标按下事件处理
*/
function mousedownHandler(event){
//计算鼠标相对滑动块的左边距,进而在鼠标移动事件处理函数中使用
//鼠标相对滑动块左边距=鼠标相对视口左边距-滑动块相对视口左边距
slider_instance.mouseLeft=event.clientX-getPageLeft(this);
console.log(getPageLeft(this));
slider_instance.outer.addEventListener("mousemove",mousemoveHandler,false);
}
/**
* 鼠标移动事件处理
*/
function mousemoveHandler(event){
//计算出应当设置的滑动块左边距(相对于父容器)
//滑动块相对于滑动条左边距=鼠标相对于视口左边距-滑动条相对于视口左边距-鼠标相对于滑动块左边距
var blockLeft=event.clientX-slider_instance.slider_bar_pageLeft-slider_instance.mouseLeft;
//如若滑动块相对于父容器左边距大于滑动块可移动宽度或小于0,表示过界;设置为左右界限值
if(blockLeft>slider_instance.slider_bar_width){
blockLeft=slider_instance.slider_bar_width
}else if(blockLeft<0){
blockLeft=0;
}
//设置滑动块的新位置
slider_instance.slider_block.style.left=blockLeft+"px";
//按照滚动块已滚动的百分比,设置被滚动元素的marginLeft(负值),进而让其滚动起来
//被滚动元素的左margin=-(滑动块相对于滑动条左边距/可滑动最大宽度*可滚动元素的最大宽度)
slider_instance.slider_content.style.marginLeft="-"+(blockLeft/slider_instance.slider_bar_width*slider_instance.slider_content_width)+"px";
}
/**
* 鼠标键弹起事件处理
*/
function mouseupHandler(event){
slider_instance.outer.removeEventListener("mousemove",mousemoveHandler,false);
}
/**
* 获得元素的视口左边距
*/
function getPageLeft(el){
var result=el.offsetLeft;
var parent=el.offsetParent;
while(parent!==null){
result+=parent.offsetLeft;
parent=parent.offsetParent;
}
return result;
}
}
//用test_div元素进行展示
new Slider(document.getElementsByClassName("test_div")[0]); }
</script>
<body>
<div class="outer">
<div class="test_div"></div>
</div>
</body>
</html>

原生JavaScript实现滚动条的更多相关文章

  1. 原生javascript模仿win8等待进度条。

    一.序言 一直很中意win8等待提示圆圈进度条.win8刚出来那会,感觉好神奇!苦于当时没思路,没去研究.通过最近网上找找资料,终于给搞出来了!先上Demo,献丑了!预览请看:win8进度条. 二.简 ...

  2. 原生javascript写的侧栏跟随效果

    浏览网站时经常看到有的网站上,当一个页面很长的时候,设定侧栏内容会跟随滚动条滚动,我们把这种效果叫做“侧栏跟随滚动”.这种特效对提高网站浏览量.文章点击率.广告点击量都有一定效果. 侧栏跟随滚动的实现 ...

  3. 原生 JavaScript 代替 jQuery【转】

    目录 用原生JavaScript代替jQuery Query Selector CSS & Style DOM Manipulation Ajax Events Utilities Promi ...

  4. 原生javascript 实现 animate

    原生javascript 实现 animate //animate function getstyle(obj,name){ if(obj.currentStyle){ return obj.curr ...

  5. 浅谈 原生javaScript&&react 实现全局触摸按钮(附带对addeventlistener的了解)

    1.采用原生javaACript 实现全局触摸按钮 首先在控制台输出,观察事件有哪些关于触摸的字段可以使用,然后拿这些字段的数据开始来写方法. 因为要做的是全局触摸按钮,我需要拿到的是按钮时时的坐标位 ...

  6. 你可能不需要 jQuery!使用原生 JavaScript 进行开发

    很多的 JavaScript 开发人员,包括我在内,都很喜欢 jQuery.因为它的简单,因为它有很多丰富的插件可供使用,和其它优秀的工具一样,jQuery 让我们开发人员能够更轻松的开发网站和 We ...

  7. 原生JavaScript技巧大收集(11~20)-(终于又被我找到这篇文章了)

    11.原生JavaScript加入收藏夹 function AddFavorite(sURL, sTitle) { try { window.external.addFavorite(sURL, sT ...

  8. javascript自定义滚动条插件,几行代码的事儿

    在实际项目中,经常由于浏览器自带的滚动条样式太戳,而且在各个浏览器中显示不一样,所以我们不得不去实现自定义的滚动条,今天我就用最少的代码实现了一个自定义滚动条,代码量区区只有几十行,使用起来也非常方便 ...

  9. 原生javascript加载运行

    原生javascript加载运行 (function(){ //TODO sometings }()); 在要运行相应代码的位置加入script标签,创建函数并自执行; 关于window.onload ...

随机推荐

  1. 如何在HTML中加载Flash(2种实现方法)_HTML/Xhtml_网页制作

    点评:如何在HTML中加载Flash,为网页添加更多的色彩,普通的网页以无法满足用户的需求,接下来为大家介绍下2种在HTML中加载Flash的方法,感兴趣的各位可以适当参考下,希望对你有所帮助 第一种 ...

  2. nullcom HackIM2016 -- Programming Question 4

    One of the NullCon vidoes talked about a marvalous Russian Gift. The Vidoe was uploaded on [May of 2 ...

  3. socket网络通信

    1.socket通常也称作"套接字",用于描述IP地址和端口.在internet上的主机一般运行了多个服务软件,同时提供几种服务,每种服务都打开一个socket,并绑定到一个端口上 ...

  4. python 连接redis工具类

    #!/usr/bin/python # coding=utf-8 __author__ = 'shuangjiang' import redis import sys default_encoding ...

  5. ReactiveCocoa框架学习<一>

    1.Cocoapods导入ReactiveCocoa: use_frameworks! target 'RACDemo' do pod 'ReactiveObjC', '~> 2.1.0' en ...

  6. 【译】RabbitMQ:路由(Routing)

    在前一篇中,我们构建了一个简单的日志系统,我们已经能够广播消息到许多的接收者.在这一篇中,我们希望增加一个特性,让订阅消息的子集成为可能.例如,我们可以将重要的错误日志存放到日志文件(即,磁盘上面), ...

  7. VS2010+C#+在新建类或接口时在文件开头自动生成作者和日期等备注

    今天在公司项目准备开始,为达到项目的规范管理,要求每个文件的标准日期,作者等信息,搜集了百度的资料,新建文件时效果如下: 其实原理很简单,只要修改VS,IDE文件下的类(或接口)模版代码 文件路径:C ...

  8. SQL图形化操作设置级联更新和删除

    SQL级联操作设置   对SQL数据库的表,进行级联操作(如级联更新及删除),首先需要设置表的主外键关系,有两种方法:   第一种:   1. 选择你要进行操作的数据库   2. 为你要创建关系的两个 ...

  9. MacDev.Mach-O.Programming-Part-III:MachOView-v2.4.9200.dmg-crash

    MachOView-v2.4.9200.dmg Crash 在OS X(其版本号: 10.11.6 (15G31))下载MachOView-2.4.9200.dmg后,打开Fat Binary后,Ma ...

  10. aspnet超级链接 传递 当前页面 textbox值

    一共有两个窗体. 第一个窗体A传参到窗体B  A的参数是A窗体的textbox 窗体A代码 <html xmlns="http://www.w3.org/1999/xhtml" ...