前面的话

  当元素内容溢出元素尺寸范围时,会出现滚动条。但由于滚动条在各浏览器下表现不同,兼容性不好。所以,模拟滚动条也是很常见的应用。本文将详细介绍滚动条模拟

原理介绍

  滚动条模拟实际上和元素模拟拖拽类似。仅仅通过范围限定,使元素只可以在单一方向上拖拽

<div id="box" style="height: 200px;width: 16px;background-color:#F5F5F5;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,0.3);position:relative;">
<div id="test" style="height: 60px;width: 16px;background-color:#555;box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:10px;position:absolute;"></div>
</div>
<script>
function addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler,false);
}else{
target.attachEvent('on'+type,function(event){
return handler.call(target,event);
});
}
}
(function(){
var y0,y1,isMoving;
var ele = document.getElementById('test'); var mousedownHandler = function(e){
e = e || event;
y0 = ele.offsetTop;
y1 = e.clientY;
//按下鼠标时,表示正在运动
isMoving = true;
}
var mousemoveHandler = function(e){
//如果没有触发down事件,而直接触发move事件,则函数直接返回
if(!isMoving){
return;
}
e = e || event;
var y2 = e.clientY;
var Y = y0 + (y2 - y1);
if(Y < 0){Y = 0;}
var YMax = parseInt(ele.parentNode.clientHeight) - ele.offsetHeight;
if(Y > YMax){Y = YMax;}
ele.style.top = Y + 'px';
}
var mouseupHandler = function(e){
//鼠标抬起时,表示停止运动
isMoving = false;
//释放全局捕获
if(ele.releaseCapture){
ele.releaseCapture();
}
}
var preventDefaultHandler = function(e){
e = e || event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
//IE8-浏览器阻止默认行为
if(ele.setCapture){
ele.setCapture();
}
}
addEvent(ele,'mousedown',mousedownHandler);
addEvent(ele,'mousedown',preventDefaultHandler);
addEvent(document,'mousemove',mousemoveHandler);
addEvent(document,'mouseup',mouseupHandler); })();
</script>

  通过将上面代码封装成函数,可以实现横向和纵向两种滚动条

<div id="box1" style="height: 200px;width: 16px;background-color:#F5F5F5;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,0.3);position:relative;">
<div id="test1" style="height: 60px;width: 16px;background-color:#555;box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:10px;position:absolute;"></div>
</div>
<div id="box2" style="height: 16px;width: 200px;background-color:#F5F5F5;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,0.3);position:relative;">
<div id="test2" style="height: 16px;width: 60px;background-color:#D62929;box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:10px;position:absolute;"></div>
</div>
<script>
function addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler,false);
}else{
target.attachEvent('on'+type,function(event){
return handler.call(target,event);
});
}
}
function scrollbar(ele,str){
var x0,x1,y0,y1,isMoving; var mousedownHandler = function(e){
e = e || event;
x0 = ele.offsetLeft;
y0 = ele.offsetTop;
x1 = e.clientX;
y1 = e.clientY;
//按下鼠标时,表示正在运动
isMoving = true;
}
var mousemoveHandler = function(e){
//如果没有触发down事件,而直接触发move事件,则函数直接返回
if(!isMoving){
return;
}
e = e || event;
if(str == 'x'){
var x2 = e.clientX;
var X = x0 + (x2 - x1);
if(X < 0){X = 0;}
var XMax = parseInt(ele.parentNode.clientWidth) - ele.offsetWidth;
if(X > XMax){X = XMax;}
ele.style.left = X + 'px';
}else{
var y2 = e.clientY;
var Y = y0 + (y2 - y1);
if(Y < 0){Y = 0;}
var YMax = parseInt(ele.parentNode.clientHeight) - ele.offsetHeight;
if(Y > YMax){Y = YMax;}
ele.style.top = Y + 'px';
} }
var mouseupHandler = function(e){
//鼠标抬起时,表示停止运动
isMoving = false;
//释放全局捕获
if(ele.releaseCapture){
ele.releaseCapture();
}
}
var preventDefaultHandler = function(e){
e = e || event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
//IE8-浏览器阻止默认行为
if(ele.setCapture){
ele.setCapture();
}
}
addEvent(ele,'mousedown',mousedownHandler);
addEvent(ele,'mousedown',preventDefaultHandler);
addEvent(document,'mousemove',mousemoveHandler);
addEvent(document,'mouseup',mouseupHandler); }; scrollbar(test1);
scrollbar(test2,'x');
</script>

应用

  下面来介绍通过滚动条实现的几个应用

数字加减

  通过移动滚动条来实现数字的加减。比例关系为:

滚动条已移动距离/滚动条可移动距离= 数字当前值/数字最大值
<div id="box" style="height: 16px;width: 200px;display:inline-block;background-color:#F5F5F5;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,0.3);position:relative;">
<div id="test" style="height: 16px;width: 60px;background-color:#D62929;box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:10px;position:absolute;"></div>
</div>
<span id="result">0</span>
<script>
function addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler,false);
}else{
target.attachEvent('on'+type,function(event){
return handler.call(target,event);
});
}
}
function scrollbar(ele,str,max){
var x0,x1,y0,y1,isMoving,radio; var mousedownHandler = function(e){
e = e || event;
x0 = ele.offsetLeft;
y0 = ele.offsetTop;
x1 = e.clientX;
y1 = e.clientY;
//按下鼠标时,表示正在运动
isMoving = true;
//x轴方向
if(str == 'x'){
ratio = max/(ele.parentNode.offsetWidth - ele.offsetWidth);
//否则为y轴方向
}else{
var disY = e.clientY - ele.offsetTop;
ratio =max/(ele.parentNode.offsetHeight - ele.offsetHeight);
}
}
var mousemoveHandler = function(e){
//如果没有触发down事件,而直接触发move事件,则函数直接返回
if(!isMoving){
return;
}
e = e || event;
if(str == 'x'){
var x2 = e.clientX;
var X = x0 + (x2 - x1);
if(X < 0){X = 0;}
var XMax = parseInt(ele.parentNode.clientWidth) - ele.offsetWidth;
if(X > XMax){X = XMax;}
ele.style.left = X + 'px';
result.innerHTML = Math.round(ratio * X);
}else{
var y2 = e.clientY;
var Y = y0 + (y2 - y1);
if(Y < 0){Y = 0;}
var YMax = parseInt(ele.parentNode.clientHeight) - ele.offsetHeight;
if(Y > YMax){Y = YMax;}
ele.style.top = Y + 'px';
result.innerHTML = Math.round(ratio * Y);
} }
var mouseupHandler = function(e){
//鼠标抬起时,表示停止运动
isMoving = false;
//释放全局捕获
if(ele.releaseCapture){
ele.releaseCapture();
}
}
var preventDefaultHandler = function(e){
e = e || event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
//IE8-浏览器阻止默认行为
if(ele.setCapture){
ele.setCapture();
}
}
addEvent(ele,'mousedown',mousedownHandler);
addEvent(ele,'mousedown',preventDefaultHandler);
addEvent(document,'mousemove',mousemoveHandler);
addEvent(document,'mouseup',mouseupHandler); }; scrollbar(test,'x',100);
</script>

元素尺寸

  通过拖动滚动条来实现元素尺寸的变化,以改变元素宽度为例。比例关系为:

滚动条已移动距离/滚动条可移动距离= 元素当前宽度/元素最大宽度
<div id="box" style="height: 16px;width: 200px;display:inline-block;background-color:#F5F5F5;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,0.3);position:relative;">
<div id="test" style="height: 16px;width: 60px;background-color:#D62929;box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:10px;position:absolute;"></div>
</div>
<span id="result" style="width: 1px;height: 50px;background-color:pink;display:inline-block;"></span>
<script>
function addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler,false);
}else{
target.attachEvent('on'+type,function(event){
return handler.call(target,event);
});
}
}
function scrollbar(ele,str,max){
var x0,x1,y0,y1,isMoving,radio; var mousedownHandler = function(e){
e = e || event;
x0 = ele.offsetLeft;
y0 = ele.offsetTop;
x1 = e.clientX;
y1 = e.clientY;
//按下鼠标时,表示正在运动
isMoving = true;
//x轴方向
if(str == 'x'){
ratio = max/(ele.parentNode.offsetWidth - ele.offsetWidth);
//否则为y轴方向
}else{
var disY = e.clientY - ele.offsetTop;
ratio =max/(ele.parentNode.offsetHeight - ele.offsetHeight);
}
}
var mousemoveHandler = function(e){
//如果没有触发down事件,而直接触发move事件,则函数直接返回
if(!isMoving){
return;
}
e = e || event;
if(str == 'x'){
var x2 = e.clientX;
var X = x0 + (x2 - x1);
if(X < 0){X = 0;}
var XMax = parseInt(ele.parentNode.clientWidth) - ele.offsetWidth;
if(X > XMax){X = XMax;}
ele.style.left = X + 'px';
result.style.width = Math.round(ratio * X) + 'px';
}else{
var y2 = e.clientY;
var Y = y0 + (y2 - y1);
if(Y < 0){Y = 0;}
var YMax = parseInt(ele.parentNode.clientHeight) - ele.offsetHeight;
if(Y > YMax){Y = YMax;}
ele.style.top = Y + 'px';
result.style.width = Math.round(ratio * Y) + 'px';
} }
var mouseupHandler = function(e){
//鼠标抬起时,表示停止运动
isMoving = false;
//释放全局捕获
if(ele.releaseCapture){
ele.releaseCapture();
}
}
var preventDefaultHandler = function(e){
e = e || event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
//IE8-浏览器阻止默认行为
if(ele.setCapture){
ele.setCapture();
}
}
addEvent(ele,'mousedown',mousedownHandler);
addEvent(ele,'mousedown',preventDefaultHandler);
addEvent(document,'mousemove',mousemoveHandler);
addEvent(document,'mouseup',mouseupHandler); }; scrollbar(test,'x',100);
</script>

内容滚动

  通过拖动滚动条来实现内容滚动,比例关系为:

滚动条已移动距离/滚动条可移动距离= 内容已移动距离/内容可移动距离
<div id="box" style="height: 200px;width: 16px;display:inline-block;background-color:#F5F5F5;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,0.3);position:relative;vertical-align:middle;">
<div id="test" style="height: 60px;width: 16px;background-color:#D62929;box-shadow:inset 0 0 6px rgba(0,0,0,.3);border-radius:10px;position:absolute;"></div>
</div>
<span id="result" style="width: 100px;height: 200px;background-color:pink;display:inline-block;line-height:30px;vertical-align:middle;position:relative;overflow:hidden;"><div id="resultIn" style="position:absolute;top:0;">测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br>测试文字<br></div></span>
<script>
function addEvent(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler,false);
}else{
target.attachEvent('on'+type,function(event){
return handler.call(target,event);
});
}
}
function scrollbar(ele,str,max){
var x0,x1,y0,y1,isMoving,radio;
var max = result.offsetHeight - resultIn.offsetHeight;
var mousedownHandler = function(e){
e = e || event;
x0 = ele.offsetLeft;
y0 = ele.offsetTop;
x1 = e.clientX;
y1 = e.clientY;
//按下鼠标时,表示正在运动
isMoving = true;
//x轴方向
if(str == 'x'){
ratio = max/(ele.parentNode.offsetWidth - ele.offsetWidth);
//否则为y轴方向
}else{
var disY = e.clientY - ele.offsetTop;
ratio =max/(ele.parentNode.offsetHeight - ele.offsetHeight);
}
}
var mousemoveHandler = function(e){
//如果没有触发down事件,而直接触发move事件,则函数直接返回
if(!isMoving){
return;
}
e = e || event;
if(str == 'x'){
var x2 = e.clientX;
var X = x0 + (x2 - x1);
if(X < 0){X = 0;}
var XMax = parseInt(ele.parentNode.clientWidth) - ele.offsetWidth;
if(X > XMax){X = XMax;}
ele.style.left = X + 'px';
resultIn.style.left = Math.round(ratio * X) + 'px';
}else{
var y2 = e.clientY;
var Y = y0 + (y2 - y1);
if(Y < 0){Y = 0;}
var YMax = parseInt(ele.parentNode.clientHeight) - ele.offsetHeight;
if(Y > YMax){Y = YMax;}
ele.style.top = Y + 'px';
resultIn.style.top = Math.round(ratio * Y) + 'px';
} }
var mouseupHandler = function(e){
//鼠标抬起时,表示停止运动
isMoving = false;
//释放全局捕获
if(ele.releaseCapture){
ele.releaseCapture();
}
}
var preventDefaultHandler = function(e){
e = e || event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
//IE8-浏览器阻止默认行为
if(ele.setCapture){
ele.setCapture();
}
}
addEvent(ele,'mousedown',mousedownHandler);
addEvent(ele,'mousedown',preventDefaultHandler);
addEvent(document,'mousemove',mousemoveHandler);
addEvent(document,'mouseup',mouseupHandler); }; scrollbar(test);
</script>

javascript动画系列第五篇——模拟滚动条的更多相关文章

  1. javascript动画系列第三篇——碰撞检测

    前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多, ...

  2. 深入理解javascript作用域系列第五篇——一张图理解执行环境和作用域

    × 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关 ...

  3. 深入理解javascript作用域系列第五篇

    前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关于作用域的两种不同翻译而已.但实际上,它们并不相同,却相 ...

  4. javascript运动系列第五篇——缓冲运动和弹性运动

    × 目录 [1]缓冲运动 [2]弹性运动 [3]距离分析[4]步长分析[5]弹性过界[6]弹性菜单[7]弹性拖拽 前面的话 缓冲运动指的是减速运动,减速到0的时候,元素正好停在目标点.而弹性运动同样是 ...

  5. javascript动画系列第四篇——拖拽改变元素大小

    × 目录 [1]原理简介 [2]范围圈定 [3]大小改变[4]代码优化 前面的话 拖拽可以让元素移动,也可以改变元素大小.本文将详细介绍拖拽改变元素大小的效果实现 原理简介 拖拽让元素移动,是改变定位 ...

  6. javascript面向对象系列第五篇——拖拽的实现

    前面的话 在之前的博客中,拖拽的实现使用了面向过程的写法.本文将以面向对象的写法来实现拖拽 写法 <style> .test{height: 50px;width: 50px;backgr ...

  7. javascript面向对象系列第五篇

    <style> .test{height: 50px;width: 50px;background-color: pink;position:absolute;} #test2{left: ...

  8. javascript动画系列第一篇——模拟拖拽

    × 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容 ...

  9. javascript面向对象系列第三篇——实现继承的3种形式

    × 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...

随机推荐

  1. my97DatePicker日期控件——日期输入框联动,使用focus使第二个输入框没展示出日期控件

    描述问题场景: 1.jquery使用的版本是jquery-1.7.2.min.js 2.代码不是写在页面上的,是通过事件后追加的 <!DOCTYPE html> <html> ...

  2. NOI 题库 9272 题解

    9272   偶数个数字3 描述 在所有的N位数中,有多少个数中有偶数个数字3? 输入 一行给出数字N,N<=1000 输出 如题 样例输入 2 样例输出 73 Solution : 令f ( ...

  3. 【第三课】WEBIX 入门自学-Hello World

    在看官网教程时,入门的例子就是dataTable这个空间.So,遵循官网,一起来看一下入门的DataTable组件: WEB使用时固然是先引入相应的库文件: 代码如下 <html> < ...

  4. dev winform导出功能

    SaveFileDialog fileDialog = new SaveFileDialog(); fileDialog.Title = "导出Excel"; fileDialog ...

  5. Akka-remote使用入门

    在上一篇文章中讲了akka-actor的简单使用,那主要是展现了akka在一台机器上的并发应用,这一篇接着介绍akka-remote使用,简单了解akka在不同机器上的并发应用.我们知道,在一台机器上 ...

  6. HttpFox

    HttpFox是Firefox的插件,可以用于HTTP分析. https://addons.mozilla.org/en-US/firefox/addon/httpfox/   安装   1. 打开F ...

  7. BSBuDeJie_04

    一 段子的下拉 建立模型 数字类型的用assign /* 当前页码 */ @property (nonatomic, assign) NSInteger page; 二 下拉上拉细节处理 三 细节处理 ...

  8. 各种android应用模仿源码

    V2EX的非官方Android客户端,极力遵循Material Design风格 下载 湘潭大学三翼校园"四季电台" Android客户端   下载   高仿煎蛋客户端    下载 ...

  9. NLP常用工具

    1.统计类工具:可参见[统计学习常用Python扩展包] 2.linux自带工具:可参见[[整理]Linux常用文本处理命令] 3.简繁转换工具:opencc Open Chinese Convert ...

  10. F.I.S初探(前端工程化)

    云笔记:http://note.youdao.com/share/?id=7c4a2dcf118f0ad7bb52a36aaee46a7a&type=note   一.初识FIS 在做项目中遇 ...