开启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. 【读书笔记】iOS-写代码注意事项

    一,我是尽早和经常编译的强烈支持者.通常,在写完每个方法或有点难度的代码后,都要尝试进行构建.这是一个好习惯,因为如果在上次成功编译以来添加的代码量很小,那么可以非常容易地缩小编译错误范围.这个方法还 ...

  2. CMD命令名详细大全

    在运行菜单里键入CMD,就可以调出CMD命令窗口,有关某个命令的详细信息,请键入 HELP 命令名 ASSOC 显示或修改文件扩展名关联. AT 计划在计算机上运行的命令和程序.ATTRIB 显示或更 ...

  3. log4net资料收集

    Log4net 日志使用介绍 http://www.cnblogs.com/jys509/p/4699813.html log4net Tutorial http://www.codeproject. ...

  4. Oracle日期周详解IW

    1 ORACLE中周相关知识描述 1.1           日期格式化函数 TO_CHAR(X [,FORMAT]):将X按FORMAT格式转换成字符串.X是一个日期,FORMAT是一个规定了X采用 ...

  5. Force.com平台基础--前言

    云计算平台 云计算模式有三种:(下面介绍来自百科) 1. SaaS:提供给客户的服务是运营商运行在云计算基础设施上的应用程序,用户可以在各种设备上通过客户端界面访问,如浏览器.消费者不需要管理或控制任 ...

  6. DNS报文格式

    原文链接地址:http://blog.chinaunix.net/uid-24875436-id-3088461.html DNS报文格式(借个图贴过来):     说明一下:并不是所有DNS报文都有 ...

  7. 烂泥:虚拟化KVM安装与配置

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 最近打算把公司的服务器全部做成虚拟化,一是跟有效的利用了服务器,二也是对自己是一个学习的机会. KVM的安装与配置步骤如下: 1. 查看是否支持虚拟化 ...

  8. linux命令后台运行

    有两种方式: 1. command & : 后台运行,你关掉终端会停止运行    2. nohup command & : 后台运行,你关掉终端也会继续运行 一. 简介     Lin ...

  9. 集成TFS Build生成与SonarQube获取代码分析结果

    软件项目在开发过程中,往往由于任务重.时间紧等原因忽略软件代码的质量和规范检查,只注重软件功能的开发和交付.等软件交付上线以后,由于代码质量导致的问题会耗费开发和运维人员的大量时间.研发表明,项目上线 ...

  10. 解决linux部署项目后,第一次访问初始化数据源的时候很慢的问题

    先说一下场景 测试环境是linux - centos6.5,项目是分布式的,分别搭建到linux上 数据货使用的是阿里巴巴数据源 每次重启后的第一次访问会比较慢,查看日志发现 卡在这个地方 ...{d ...