开启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. 百度地图API说明

    JZ's Blog的博客对百度地图说明很清晰 http://www.jiazhengblog.com/blog/2011/07/02/289/

  2. Node.js(2)-protobuf zeromq gzip

    1.Node.Js环境准备 在win8 + vs.net 2012 环境下调试了很长时间没搞定安装编译问题,重装系统测试了2套环境,解决了编译问题: 1)Win8.1 + vs.net 2013 2) ...

  3. Effective Java 13 Minimize the accessibility of classes and members

    Information hiding is important for many reasons, most of which stem from the fact that it decouples ...

  4. SQL 递归查询(根据指定的节点向上获取所有父节点,向下获取所有子节点)

    --------------------01.向上查找所有父节点-----------------WITH TEMP AS (SELECT * FROM CO_Department WHERE ID= ...

  5. Cocos2d-x分类

    Cocos2d-x win7 + vs2010 配置图文详解(亲测) Cocos2d-x建工程时避免copy文件夹和库

  6. Linux Shell 02 流程控制语句

    一.if语句格式:支持if/elif/else形式,支持嵌套 1. command执行成功(及退出状态为0)时,执行command2 2. 当判断条件为test命令时,判断结果为true时,执行com ...

  7. 问题解决——VS2010 将生成的文件复制到指定位置

    我是从VC6直接过渡到VS2010的,VS2008没怎么用过.用VS2010的时候,每次生成dll后,手工把dll.lib..h文件复制到指定文件夹太麻烦了,所以着手写了这个. =========== ...

  8. IdentityHashMap的使用场景

    IdentityHashMap的使用场景 JDK1.4就加入了这个map类型,它是使用 == 判断相等,而不是hashmap的equals方法判断相等. 那么,它有什么应用场合呢? 当然是需要我们必须 ...

  9. XSLT

    一.简介 XSLT 是一种用于将 XML 文档转换为 XHTML 文档或其他 XML 文档的语言. XSL(eXtensible Stylesheet Language) -- 可扩展标记语言,主要用 ...

  10. SecureCRT 使用技巧

    VanDyke CRT 和 VanDyke SecureCRT是最常用的终端仿真程序,简单的说就是windows下登录UNIX或Liunx服务器主机的软件.二者不同的是SecureCRT支持SSH∗( ...