开启setInterval定时器之前,请先清除之前的定时器

window.onload = function() {
var btn = document.getElementById('btn');
var oDiv = document.getElementById('div1');
var timer = null; btn.onclick = function() {
clearInterval(timer); // 避免定时器叠加
var timer = setInterval(function() { // 设置定时器,定义动画
if (oDiv.offsetLeft > 300) { // 动画的结束条件
clearInterval(timer);
}else { // 动画的内容
oDiv.style.left = oDiv.offsetLeft + 10 + 'px';
}
}, 30);
};
};

用函数封装动画

var timer = null;
// elem: 运动的元素
// iTarget: 运动的目标
// iSpeed: 动画的速度
function animate(elem, iTarget, iSpeed) {
clearInterval(timer);
timer = setInterval(function() {
var offsetLeft = elem.offsetLeft;
if(offsetLeft > iTarget) {
clearInterval(timer);
}else {
elem.style.left = offsetLeft + iSpeed + 'px';
}
}, 30);
}

运动框架的基本步骤:

1. 清除定时器

2. 开启定时器,计算速度

3. 判断停止条件,执行运动

根据目标判断速度方向

var timer = null;
// elem: 运动的元素
// iTarget: 运动的目标
// iSpeed: 速度
function animate(elem, iTarget, iSpeed) { clearInterval(timer);
timer = setInterval(function() {
var offsetLeft = elem.offsetLeft;
// 计算速度
iSpeed = offsetLeft < iTarget ? iSpeed : - iSpeed;
if(offsetLeft === iTarget) {
clearInterval(timer);
}else {
elem.style.left = offsetLeft + iSpeed + 'px';
}
}, 30);
}

淡入淡出,改变元素的透明度。需要有一个变量保存透明度值,用来和速度加减,然后赋值给元素的样式,从而实现淡入淡出。

var timer = null;
var opacity = 30; // 默认透明度
function animate(elem, iTarget, iSpeed) {
// 计算速度
iSpeed = opacity < iTarget ? iSpeed : - iSpeed; clearInterval(timer);
timer = setInterval(function() {
if(opacity === iTarget) {
clearInterval(timer);
}else {
opacity += iSpeed; // 改变当前透明度
elem.style.filter = 'alpha(opacity:' + opacity + ')';
elem.style.opacity = opacity / 100;
}
}, 30);
}

缓冲运动,改变速度值,每次累加的速度值变小,物体改变的距离越来越变小。

物体运动逐渐变慢,最后停止。

对于速度:距离越远,速度越大;速度 = (目标点-当前值)/ 缩放系数

问题:1. 速度需要取整(正向速度向上取整,负向速度向下取整)原因是样式的像素会舍去小数部分

2. 潜在问题,目标值不是整数时(跟随页面滚动的缓冲侧边栏)

var timer = null;
function animate(elem, iTarget) { clearInterval(timer);
timer = setInterval(function() {
var offsetLeft = elem.offsetLeft;
// 对正向速度向上取整,对负向速度向下取整
var iSpeed = (iTarget - offsetLeft) / 8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if(offsetLeft === iTarget) { // 运动停止条件
clearInterval(timer);
}else {
elem.style.left = offsetLeft + iSpeed + 'px';
}
}, 30);
}

运动终止条件

匀速运动,与目标点足够近(距离小于速度时,可把目标设为物体的终点);

利用绝对值可以避免判断方向问题

缓冲运动,与目标点重合;

多物体运动

每个运动物体都能开启一个属于自己的定时器。做法把定时器作为物体的属性,这样清理时针对自己。

参数的传递,物体与目标值

关键点,所有变量不能共享。(如把定时器变量作为物体的属性)

function animate(elem, iTarget) {

    clearInterval(elem.timer);
elem.timer = setInterval(function() {
var offsetWidth = elem.offsetWidth;
// 对正向速度向上取整,对负向速度向下取整
var iSpeed = (iTarget - offsetWidth) / 8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if(offsetWidth === iTarget) { // 运动停止条件
clearInterval(elem.timer);
}else {
elem.style.width = offsetWidth + iSpeed + 'px';
}
}, 30);
}

多物体淡入淡出时,也出现同样的情况。必须针对每一个物体设置透明度属性(不能共享,只能独享)

function animate(elem, iTarget) {

    clearInterval(elem.timer);
elem.timer = setInterval(function() { // 对正向速度向上取整,对负向速度向下取整
var iSpeed = (iTarget - elem.opacity) / 8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if(elem.opacity === iTarget) { // 运动停止条件
clearInterval(elem.timer);
}else {
elem.opacity += iSpeed;
elem.style.filter = 'alpha(opacity:'+ elem.opacity +')';
elem.style.opacity = elem.opacity / 100;
}
}, 30);
}

物体大小属性(offsetWidth / offsetHeight)的Bug。

原因:offsetWidth包含了border的宽,对拥有边框的div不等于其width属性

解决办法:获取真正的width值。

// 返回指定属性的属性值
// 返回值是字符串数字(带有单位)
function getStyle(elem, attr) {
var value = null;
if(elem.currentStyle) {
value = elem.currentStyle[attr];
}else {
value = getComputedStyle(elem, null)[attr];
}
return value;
}

任意值运动

高度、宽度、透明度、位置。抽象animate函数

function animate(elem, attr, iTarget) {

    clearInterval(elem.timer);
elem.timer = setInterval(function() {
var iCur = getStyle(elem, attr); // 获取当前attr属性值
if (attr === 'opacity') {
iCur = parseFloat(iCur * 100);
}
iCur = parseInt(iCur); // 转换成整形,待计算 var iSpeed = (iTarget - iCur) / 8; // 缓冲运动计算每次速度
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur === iTarget) {
clearInterval(elem.timer);
}else {
if (attr === 'opacity') {
iCur += iSpeed;
elem.style.filter = 'alpha(opacity:'+ iCur +')';
elem.style.opacity = iCur / 100;
}else {
elem.style[attr] = iCur + iSpeed + 'px';
}
}
}, 30);
}

链式运动

简单地说,一个动画结束时另一个动画开始。(利用回调函数)

function animate(elem, attr, iTarget, callback) {

    clearInterval(elem.timer);
elem.timer = setInterval(function() {
var iCur = getStyle(elem, attr); // 获取当前attr属性值
if (attr === 'opacity') {
iCur = parseFloat(iCur * 100);
}
iCur = parseInt(iCur); // 转换成整形,待计算 var iSpeed = (iTarget - iCur) / 8; // 缓冲运动计算每次速度
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur === iTarget) {
clearInterval(elem.timer);
callback && callback();
}else {
if (attr === 'opacity') {
iCur += iSpeed;
elem.style.filter = 'alpha(opacity:'+ iCur +')';
elem.style.opacity = iCur / 100;
}else {
elem.style[attr] = iCur + iSpeed + 'px';
}
}
}, 30);
}
window.onload = function() {
var oBtn = document.getElementById('btn');
var oDiv = document.getElementById('div1'); oBtn.onclick = function() {
animate(oDiv, 'left', 800, function() { // 向右滑动到800px
animate(oDiv, 'width', 300, function() { // 然后,宽度增大到300
animate(oDiv, 'height', 400, function() { // 然后,高度增大到400
animate(oDiv, 'opacity', 100); // 最后,透明度为不透明
});
});
});
}; };

多属性同时改变

目前的运动框架每次运动只能改变一种属性的值.可以通过传递属性/目标值组成的字面量,来同时改变多个属性。

// 返回指定属性的属性值
function getStyle(elem, attr) {
var value = null;
if(elem.currentStyle) {
value = elem.currentStyle[attr];
}else {
value = getComputedStyle(elem, null)[attr];
}
return value;
} // attrs 多属性组成的字面量对象
function animate(elem, attrs, callback) { clearInterval(elem.timer);
elem.timer = setInterval(function() {
bStop = true; // 检查所有的属性是否已经达到目标
for(var attr in attrs) { // 遍历每一个属性 var iCur = getStyle(elem, attr); // 获取当前attr属性值
if (attr === 'opacity') {
iCur = parseFloat(iCur * 100);
}
iCur = parseInt(iCur); // 转换成整形,待计算 var iSpeed = (attrs[attr] - iCur) / 8; // 缓冲运动计算每次速度
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); if (iCur !== attrs[attr]) {
bStop = false;
if (attr === 'opacity') {
iCur += iSpeed;
elem.style.filter = 'alpha(opacity:'+ iCur +')';
elem.style.opacity = iCur / 100;
}else {
elem.style[attr] = iCur + iSpeed + 'px';
}
}
}
if (bStop) { // 所有属性值已达到给定的目标值
clearInterval(elem.timer);
callback && callback();
};
}, 30);
} window.onload = function() {
var oBtn = document.getElementById('btn');
var oDiv = document.getElementById('div1'); oBtn.onclick = function() {
animate(oDiv, {width: 500, height: 600, opacity: 100});
}; };

分享到例子

主要根据目标判断速度的正负,从而在鼠标滑入滑出时候进行运动或恢复效果

<div id="div1">

<div id="share_btn">分享到</div>

</div>

body {

margin: 0;

padding: 0;

}

#div1 {

width: 100px;

height: 200px;

background-color: #aaf6f8;

/* 动画的div设置为绝对定位 */

position: absolute;

top: 40%;

left: -100px;

margin-top: -100px;

}

/* 分享按钮,固定宽度用于定位,高度由内容决定 */

#share_btn {

width: 28px;

padding: 8px 0;

background-color: #00F;

text-align: center;

color: #FFF;

position: absolute;

right: -28px;

top: 50%;

margin-top: -40px;

}

window.onload = function() {
var oDiv = document.getElementById('div1');
var share_btn = document.getElementById('share_btn');
// 展示分享到信息
oDiv.onmouseover = share_btn.onmouseover = function() {
animate(oDiv, 0, 10);
};
// 恢复分享到状态
oDiv.onmouseout = share_btn.onmouseout = function() {
animate(oDiv, -100, 10);
};
};
var timer = null;
// elem: 运动的元素
// iTarget: 运动的目标
// iSpeed: 速度
function animate(elem, iTarget, iSpeed) {
// 计算速度
iSpeed = elem.offsetLeft < iTarget ? iSpeed : - iSpeed; clearInterval(timer);
timer = setInterval(function() {
var offsetLeft = elem.offsetLeft;
if(offsetLeft === iTarget) {
clearInterval(timer);
}else {
elem.style.left = offsetLeft + iSpeed + 'px';
}
}, 30);
}
推荐智能社Javascript系列视频教程

js运动框架 step by step的更多相关文章

  1. 带无缝滚动的轮播图(含JS运动框架)

    今天学习了一下轮播图的写作,想到前一阵学过的无缝滚动得思想,所以就把轮播与滚动结合了一下.不过我的代码的神逻辑我自己都不敢恭维,在没网没参照的情况下,只能硬着头皮往下写,希望跟大家共勉吧. js运动框 ...

  2. js运动框架之一条乱跑的虫子

    克隆与运动框架的联合应用 效果:点击元素块后,元素块开始随机的向任何方向移动,并附带一堆颜色随机的"尾巴".每个方向运动3秒后改变方向,同时笑脸变哭脸. 如图所示: 朝某个方向运动 ...

  3. JS运动框架的封装过程(一)

    给大家出一道题,从起点A走到目的地B,一共用了1000毫秒,每一次是30毫秒,请问你在这里面得到了哪些信息? 信息有哪些呢? 第一个,总时长是:1000毫秒 第二个,多久时间走一次?30毫秒 第三个, ...

  4. js 运动框架及实例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. js运动框架逐渐递进版

    运动,其实就是在一段时间内改变left.right.width.height.opactiy的值,到达目的地之后停止. 现在按照以下步骤来进行我们的运动框架的封装: 匀速运动. 缓冲运动. 多物体运动 ...

  6. js运动框架之掉落的扑克牌(重心、弹起效果)

    玩过电脑自带纸牌游戏的同志们应该都知道,游戏过关后扑克牌会依次从上空掉落,落下后又弹起,直至"滚出"屏幕. 效果如图:    这个案例的具体效果就是:点击开始运动,纸牌会从右上角掉 ...

  7. js运动框架完成块的宽高透明度及颜色的渐变

    了解了运动框架完成块元素的宽高和透明度的变化的原理,我想着写一个颜色的变化来练习一下,不想写了很长时间才写出来,跟各位分享一下. 颜色的变化是通过三元素渐变的方式完成的,通过构造json,使当前的颜色 ...

  8. 完美的js运动框架

    //完美运动框架, 对象,json,函数function move(obj,json,funEnd){clearInterval(obj.timer);//清除定时器obj.timer= setInt ...

  9. js 运动框架-轻量级

    具体代码如下: function move(obj,json,sv,fnEnd){ //CSS样式值 function getStyle(obj,attr){ if(obj.currentStyle) ...

随机推荐

  1. iptables基本操作

    一.基本操作 #启动防火墙 service iptables start #停止防火墙 service iptables stop #重启防火墙 service iptables restart #查 ...

  2. 【读书笔记】iOS-忽略编译警告

    一,忽略编译警告的命令. -w   禁止掉所有的编译警告. -Wno-unused-variable  只禁止掉未使用的变量的编译警告. 二,忽略编译警告的方法. targets--->Buil ...

  3. 设计模式:模版模式(Template Pattern)-转

    模版模式 又叫模板方法模式,在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情冴下,重新定义算法中的某些步骤. 我们使用冲泡咖啡和冲泡茶的例子 加工流程 ...

  4. Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)

    Java中==.equals.hashcode的区别与重写equals以及hashcode方法实例  原文地址:http://www.cnblogs.com/luankun0214/p/4421770 ...

  5. IOS开发之网络编程--文件压缩和解压缩

    前言: QQ表情包就用到了解压缩,从网络下载的那么多表情文件格式并不是一个一个图片文件,而是多个图片压缩而成的表情压缩包.下面介绍的是iOS开发中会用到的压缩和解压缩的第三方框架的使用. 注意: 这个 ...

  6. spring aop 拦截业务方法,实现权限控制

    难点:aop类是普通的java类,session是无法注入的,那么在有状态的系统中如何获取用户相关信息呢,session是必经之路啊,获取session就变的很重要.思索很久没有办法,后来在网上看到了 ...

  7. java网络---查找Internet

    连接到Internet的设备称为节点,计算机节点称为host. 为了区别每一台连接互联网的计算机,就有了Internet Protocol地址的概念. IPV4 & IPV6 我们以前默认的是 ...

  8. canvas & animation

    1.using canvas using canvas to set difference property. it will showing like an animation. The true ...

  9. C++中的多态与虚函数的内部实现

    1.什么是多态         多态性可以简单概括为“一个接口,多种行为”.         也就是说,向不同的对象发送同一个消息, 不同的对象在接收时会产生不同的行为(即方法).也就是说,每个对象可 ...

  10. Effective Java 72 Don't depend on the thread scheduler

    Principle Any program that relies on the thread scheduler for correctness or performance is likely t ...