[js高手之路]打造通用的匀速运动框架
本文,是接着上文[js高手之路]匀速运动与实例实战(侧边栏,淡入淡出)继续的,在这篇文章的最后,我们做了2个小实例:侧边栏与改变透明度的淡入淡出效果,本文我们把上文的animate函数,继续改造,让他变得更加的通用和强大:
1,支持多个物体的运动
2,同时运动
3,顺序运动
这三种运动方式也是jquery中animate函数支持的
一、animate函数中怎么区分变化不同的样式?
上文中,侧边栏效果 用的animate函数 改变的是left值
function animate(obj, target, speed) {
clearInterval(timer);
timer = setInterval(function () {
if (obj.offsetLeft == target) {
clearInterval(timer);
} else {
obj.style.left = obj.offsetLeft + speed + 'px';
}
}, 30);
}
淡入淡出效果 用的animate函数 改变的是透明度
function animate(obj, target, speed) {
clearInterval(timer);
var cur = 0;
timer = setInterval(function () {
cur = css( obj, 'opacity') * 100;
if( cur == target ){
clearInterval( timer );
}else {
cur += speed;
obj.style.opacity = cur / 100;
obj.style.filter = "alpha(opacity:" + cur + ")";
}
}, 30);
}
而我们封装的函数,要变成通用的,首先面临的问题就是 这个函数要同时支持left值和透明度的变化,更通用的做法应该是要支持所有的样式变化,比如轮播功能,他有左右滑动,也有上下滑动。
我们可以在获取样式和改变样式的时候,做一下判断就可以了,判断分2类就能达到目的,因为其他样式( margin, left, top, right, font-size等等 )都是px,而透明度没有px单位
function animate(obj, attr, target, speed) {
clearInterval(timer);
var cur = 0;
timer = setInterval(function () {
if (attr == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, attr));
}
if (cur == target) {
clearInterval(timer);
} else {
if (attr == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[attr] = cur + speed + "px";
}
}
}, 30);
}
合并之后的animate相比之前多了一个参数attr, 这个参数就是变化的样式,obj: 变化的对象, target: 样式需要变化到的目标值. speed: 样式每次变化的大小
如:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>合并的运动 - by ghostwu</title>
<style>
img {
border: none;
opacity: 0.3;
filter: alpha(opacity:30);
position: absolute;
left: 200px;
} #box {
width: 150px;
height: 300px;
background: red;
position: absolute;
left: -150px;
top: 50px;
} #box div {
width: 28px;
height: 100px;
position: absolute;
right: -28px;
top: 100px;
background: green;
}
</style>
<script>
window.onload = function () {
var oImg = document.getElementById("img"),
oBox = document.getElementById("box"),
timer = null; oImg.onmouseover = function () {
animate(this, 'opacity', 100, 10);
}
oImg.onmouseout = function () {
animate(this, 'opacity', 30, -10);
} oBox.onmouseover = function () {
animate(this, 'left', 0, 10);
} oBox.onmouseout = function () {
animate(this, 'left', -150, -10);
} function animate(obj, attr, target, speed) {
clearInterval(timer);
var cur = 0;
timer = setInterval(function () {
if (attr == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, attr));
} if (cur == target) {
clearInterval(timer);
} else {
if (attr == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[attr] = cur + speed + "px";
}
}
}, 30);
} function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="box">
<div>分享到</div>
</div>
<img src="./img/h4.jpg" alt="" id="img"/>
</body>
</html>
上述就是完整的代码实例,请自行展开,点击run code预览效果
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
img {
border: none;
opacity: 0.3;
filter: alpha(opacity:30);
position: absolute;
left: 200px;
}
#box {
width: 150px;
height: 300px;
background: red;
position: absolute;
left: -150px;
top: 50px;
}
#box div {
width: 28px;
height: 100px;
position: absolute;
right: -28px;
top: 100px;
background: green;
}
</style>
<script>
window.onload = function () {
var oImg = document.getElementById("img"),
oBox = document.getElementById("box"),
timer = null;
oImg.onmouseover = function () {
animate(this, 'opacity', 100, 10);
}
oImg.onmouseout = function () {
animate(this, 'opacity', 30, -10);
}
oBox.onmouseover = function () {
animate(this, 'left', 0, 10);
}
oBox.onmouseout = function () {
animate(this, 'left', -150, -10);
}
function animate(obj, attr, target, speed) {
clearInterval(timer);
var cur = 0;
timer = setInterval(function () {
if (attr == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, attr));
}
if (cur == target) {
clearInterval(timer);
} else {
if (attr == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[attr] = cur + speed + "px";
}
}
}, 30);
}
function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="box">
<div>分享到</div>
</div>
<img src="http://images2017.cnblogs.com/blog/253192/201710/253192-20171015095909480-1867777993.png" alt="" id="img"/>
</body>
</html>
run code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
img {
border: none;
opacity: 0.3;
filter: alpha(opacity:30);
position: absolute;
left: 200px;
} #box {
width: 150px;
height: 300px;
background: red;
position: absolute;
left: -150px;
top: 50px;
} #box div {
width: 28px;
height: 100px;
position: absolute;
right: -28px;
top: 100px;
background: green;
}
</style>
<script>
window.onload = function () {
var oImg = document.getElementById("img"),
oBox = document.getElementById("box"); oImg.onmouseover = function () {
animate(this, 'opacity', 100, 10);
}
oImg.onmouseout = function () {
animate(this, 'opacity', 30, -10);
} oBox.onmouseover = function () {
animate(this, 'left', 0, 10);
} oBox.onmouseout = function () {
animate(this, 'left', -150, -10);
} function animate(obj, attr, target, speed) {
clearInterval(obj.timer);
var cur = 0;
obj.timer = setInterval(function () {
if (attr == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, attr));
} if (cur == target) {
clearInterval(obj.timer);
} else {
if (attr == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[attr] = cur + speed + "px";
}
}
}, 30);
} function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="box">
<div>分享到</div>
</div>
<img src="./img/h4.jpg" alt="" id="img"/>
</body>
</html>
至此,我们就完成了多物体运动与不同样式的修改
二、让animate函数支持多个样式同时改变
比如:
oBox.onmouseover = function(){
animate( this, { "width" : 500, "height" : 400 }, 10 );
}
oBox是一个div元素,animate各参数的意思:
this: 当前div元素
{width : 500, "height" : 400 } : 把宽度变成500, 高度变成400,这两个样式要在同一时间完成,
10: 样式每次在原来的基础上变化10(如width初始值200--> 210, 220, 230.....)
完整的同时运动变化 代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div {
width: 200px;
height: 200px;
background: red;
}
</style>
<script>
window.onload = function () {
var oBox = document.getElementById("box");
oBox.onmouseover = function(){
// animate( this, { "width" : 500, "height" : 500 }, 10 );
animate( this, { "width" : 500, "height" : 400 }, 10 );
} function animate(obj, attr, speed) {
clearInterval(obj.timer);
var cur = 0;
obj.timer = setInterval(function () {
for ( var key in attr ) {
if (key == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, key));
}
var target = attr[key];
if (cur == target) {
clearInterval(obj.timer);
} else {
if (key == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[key] = cur + speed + "px";
}
}
}
}, 30);
} function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
请自行展开这段代码,这段代码能够同时运动,但是有一个问题:
div的初始宽度与高度( width : 200, height : 200)
变化步长一样( 10 )
变化时间一样( 每30毫秒变化一次 )
目标( width: 500, height : 400 )
你能想到什么问题吗?( 两个人在同一起跑线上,速度一样, 时间一样,但是要同时到达不同的目标,一个500, 一个400 )
答案是很明显的,肯定是目标近的( height : 400 )那个先到达,然后把对象上的定时器关了,另一个目标更远的( width: 500 )肯定到达不了
你可以在这句代码下面,输出当前的值和目标值:
输出来的结果是:


从上图可以看出,height已经达到了400px,但是width停在了410px,为什么不是400px ? 因为width = 400的时候, 就是( cur == 500 ) 相当于( 400 == 500 ) 不成立,所以执行了else语句,width = cur + 10 = 400 + 10 = 410,然后height到达400px停止了定时器,所以width停在了410px.
那么我们怎么解决这个问题呢?
其实也好办,就是height = 400的时候 不要把定时器关了,应该等width = 500的时候再关闭定时器,不就在同一时间,完成了同时到达目标的效果吗?
修改后的代码如下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div {
width: 200px;
height: 200px;
background: red;
}
</style>
<script>
window.onload = function () {
var oBox = document.getElementById("box");
oBox.onmouseover = function(){
animate( this, { "width" : 500, "height" : 400 }, 10 );
} function animate(obj, attr, speed) {
clearInterval(obj.timer);
var cur = 0;
obj.timer = setInterval(function () {
var bFlag = true;
for ( var key in attr ) {
if (key == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, key));
}
var target = attr[key];
if (cur != target) {
bFlag = false;
if (key == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[key] = cur + speed + "px";
}
}
}
if ( bFlag ) {
clearInterval( obj.timer );
}
}, 30);
} function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
声明一个变量,每次变化完一次( width, height )样式 把bFlag = true, 只要在for循环中有一个没有到达目标,bFlag的值都是false,这样就不会关闭定时器。当两个都到达目标,才关闭定时器.
三、顺序运动
如样式变化,按顺序来,不是同时变化, 如:
oBox.onmouseover = function(){
//回调函数: 把函数当做参数传递给另一个函数
animate( this, { 'width' : 500 }, 10, function(){
animate( this, { 'height' : 500 }, 10 );
} );
}
当把width变成500px的时候,如果传递了回调函数, 再接着执行回调函数里面的运动
修改后的完整代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>通用的匀速运动框架 - by ghostwu</title>
<style>
div {
width: 200px;
height: 200px;
background: red;
}
</style>
<script>
window.onload = function () {
var oBox = document.getElementById("box");
oBox.onmouseover = function(){
//回调函数: 把函数当做参数传递给另一个函数
animate( this, { 'width' : 500 }, 10, function(){
animate( this, { 'height' : 500 }, 10 );
} );
} function animate(obj, attr, speed, fn ) { clearInterval(obj.timer);
var cur = 0;
obj.timer = setInterval(function () {
var bFlag = true;
for (var key in attr) {
if (key == 'opacity') {
cur = css(obj, 'opacity') * 100;
} else {
cur = parseInt(css(obj, key));
}
var target = attr[key];
if (cur != target) {
bFlag = false;
if (key == 'opacity') {
obj.style.opacity = ( cur + speed ) / 100;
obj.style.filter = "alpha(opacity:" + (cur + speed) + ")";
} else {
obj.style[key] = cur + speed + "px";
}
}
} if (bFlag) {
clearInterval(obj.timer);
fn && fn.call( obj );
}
}, 30);
} function css(obj, attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
}
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
[js高手之路]打造通用的匀速运动框架的更多相关文章
- [js高手之路] 我的开源javascript框架gdom - 选择器用法
gdom框架是我开发的一款dom和字符串处理框架,目前版本是1.0.0. 使用方法跟jquery是差不多的, 会用jquery就会用gdom,目前 1.0.0版本的选择器完全支持CSS3选择器.没有做 ...
- [js高手之路]面向对象版本匀速运动框架
这篇文章的效果,需要看过以下3篇文章: [js插件开发教程]一步步开发一个可以定制配置的隔行变色小插件 [js高手之路]匀速运动与实例实战(侧边栏,淡入淡出) [js高手之路]打造通用的匀速运动框架 ...
- [js高手之路]封装运动框架实战左右与上下滑动的焦点轮播图
在这篇文章[js高手之路]打造通用的匀速运动框架中,封装了一个匀速运动框架,我们在这个框架的基础之上,加上缓冲运动效果,然后用运动框架来做幻灯片(上下,左右),效果如下: 1 2 3 4 5 // 0 ...
- [js高手之路]深入浅出webpack教程系列4-插件使用之html-webpack-plugin配置(上)
还记得我们上文中的index.html文件吗? 那里面的script标签还是写死的index.bundle.js文件,那么怎么把他们变成动态的index.html文件,这个动态生成的index.htm ...
- [js高手之路]Node.js实现简易的爬虫-抓取博客文章列表信息
抓取目标:就是我自己的博客:http://www.cnblogs.com/ghostwu/ 需要实现的功能: 抓取文章标题,超链接,文章摘要,发布时间 需要用到的库: node.js自带的http库 ...
- [js高手之路]html5 canvas动画教程 - 边界判断与小球粒子模拟喷泉,散弹效果
备注:本文后面的代码,如果加载了ball.js,那么请使用这篇文章[js高手之路] html5 canvas动画教程 - 匀速运动的ball.js代码. 本文,我们要做点有意思的效果,首先,来一个简单 ...
- [js高手之路]html5 canvas动画教程 - 边界判断与反弹
备注:本文后面的代码,如果加载了ball.js,那么请使用这篇文章[js高手之路] html5 canvas动画教程 - 匀速运动的ball.js代码. 边界反弹: 当小球碰到canvas的四个方向的 ...
- [js高手之路]Node.js实现简易的爬虫-抓取博客所有文章列表信息
抓取目标:就是我自己的博客:http://www.cnblogs.com/ghostwu/ 需要实现的功能: 抓取博客所有的文章标题,超链接,文章摘要,发布时间 需要用到的库: node.js自带的h ...
- [js高手之路] es6系列教程 - 对象功能扩展详解
第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...
随机推荐
- 团队作业8——第二次项目冲刺(Beta阶段)博客汇总
一.冲刺计划安排 http://www.cnblogs.com/teamworkers/p/6875742.html 二.七天冲刺汇总 http://www.cnblogs.com/teamworke ...
- 201521123057 《Java程序设计》 第7周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 答:源代码: pub ...
- 201521123020 《Java程序设计》第6周学习总结
本周学习总结 书面作业 1.clone方法 1.1 Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么? 答:需要将protected改为pu ...
- 201521123045 《Java程序设计》第4周学习总结
第4周作业-面向对象设计与继承 1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 2. 书面作业 Q1.注释的应用使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclip ...
- 201521123065《java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 1.多线程的临界资源:启动多个线程同时运行时,需要同时访问共同的资源,导致结果的不正确性: 2.原子性操作:只进行 ...
- 201521123068《Java程序设计》第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...
- Linux帮助手册(man)
Linux的帮助文档 在我们使用Linux的过程中,都会遇到这样那样的问题,一般我们在计算机能连上网的情况下会进行百度或Google解决问题,但是并不是所有文题都能在网上很快得到答案.万一我们是在没有 ...
- shell脚本之算术运算和逻辑运算
目录 算术运算 赋值运算 逻辑运算 短路运算和异或 条件测试 数值测试 字符串测试 文件及其属性测试 存在性测试 存在性及类别测试 文件权限测试 文件特殊权限测试 文件大小测试 文件是否打开 双目测试 ...
- Js前端传递json数组至服务器端并解析的实现。
最近做的一个小项目中需要将json数组数据传递到服务器端进行保存,现分享一下解决思路. 环境:EasyUi+Mvc 4.0 如下: 在上述截图中的红色圈起来的部分,需要在点击保存后通过一次ajax请求 ...
- C3P0 WARN: Establishing SSL connection without server's identity verification is not recommended
c3p0的出现,是为了大大提高应用程序和数据库之间访问效率的. 它的特性: 编码的简单易用 连接的复用 连接的管理 今天在配置C3p0的时候出现了这个warn 原因是因为要验证SSL Wed Se ...