开启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 图片轮播实现原理 (三图)

    IOS 图片轮播实现原理的一种 图片轮播所要实现的是在一个显示区域内通过滑动来展示不同的图片. 当图片较少时我们可以采用在滚动视图上添加很多张图片来实现. 但是如果图片数量较多时,一次性加载过多图片会 ...

  2. JQuery判断radio是否选中,获取选中值

    本文摘自:http://www.cnblogs.com/xcj1989/archive/2011/06/29/JQUERY_RADIO.html   /*----------------------- ...

  3. 【AdaBoost算法】积分图代码实现

    一.积分图介绍 定义:图像左上方的像素点值的和: 在Adaboost算法中可用于加速计算Haar或MB-LBP特征值,如下图: 二.代码实现 #include <opencv/highgui.h ...

  4. 团队管理_效率开会[持续更新ing]

    1.明确开会目的,这个会议是用来解决什么问题,得出什么结果. 2.明确会议内容与流程,简要说明会议分几个部分,一步一步推进会议的进行. 3.保证参会人员守时参加,会议准时开始. 4.保证会议时间尽量为 ...

  5. kettle初探

    Kettle是Pentaho的一个组件,主要用于数据库间的数据迁移,到我用过的4.2版,还不支持noSQL,不知道4.4是不是支持了. Kettle自己有三个主要组件:Spoon,Kitchen,Pa ...

  6. 解读Python发送邮件

    解读Python发送邮件 Python发送邮件需要smtplib和email两个模块.也正是由于我们在实际工作中可以导入这些模块,才使得处理工作中的任务变得更加的简单.今天,就来好好学习一下使用Pyt ...

  7. sql 查询基本语法

    1.计算列        select * from emp           --*表示所有的           --from emp 表示从emp表查询   select empno,enam ...

  8. JVM 垃圾回收算法

    在说垃圾回收算法之前,先谈谈JVM怎样确定哪些对象是“垃圾”. 1.引用计数器算法: 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1,当 ...

  9. [麦先生]如何使用AJAX实现按需加载

    按需加载的优势:在实际调查中发现,很多的网民在游览网站时具有明确的指向性,往往在进入主页后直接搜索进入自己需要的商品列表内,如果在客户进入主页时将主页信息全部加载完毕后展示给顾客,会极大的浪费网站资源 ...

  10. Golang gRPC 示例

    1.安装gRPC runtime go get google.golang.org/grpc 为了自动生成Golang的gRPC代码,需要安装protocal buffers compiler以及对应 ...