js运动框架 step by step
开启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);
}
js运动框架 step by step的更多相关文章
- 带无缝滚动的轮播图(含JS运动框架)
今天学习了一下轮播图的写作,想到前一阵学过的无缝滚动得思想,所以就把轮播与滚动结合了一下.不过我的代码的神逻辑我自己都不敢恭维,在没网没参照的情况下,只能硬着头皮往下写,希望跟大家共勉吧. js运动框 ...
- js运动框架之一条乱跑的虫子
克隆与运动框架的联合应用 效果:点击元素块后,元素块开始随机的向任何方向移动,并附带一堆颜色随机的"尾巴".每个方向运动3秒后改变方向,同时笑脸变哭脸. 如图所示: 朝某个方向运动 ...
- JS运动框架的封装过程(一)
给大家出一道题,从起点A走到目的地B,一共用了1000毫秒,每一次是30毫秒,请问你在这里面得到了哪些信息? 信息有哪些呢? 第一个,总时长是:1000毫秒 第二个,多久时间走一次?30毫秒 第三个, ...
- js 运动框架及实例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- js运动框架逐渐递进版
运动,其实就是在一段时间内改变left.right.width.height.opactiy的值,到达目的地之后停止. 现在按照以下步骤来进行我们的运动框架的封装: 匀速运动. 缓冲运动. 多物体运动 ...
- js运动框架之掉落的扑克牌(重心、弹起效果)
玩过电脑自带纸牌游戏的同志们应该都知道,游戏过关后扑克牌会依次从上空掉落,落下后又弹起,直至"滚出"屏幕. 效果如图: 这个案例的具体效果就是:点击开始运动,纸牌会从右上角掉 ...
- js运动框架完成块的宽高透明度及颜色的渐变
了解了运动框架完成块元素的宽高和透明度的变化的原理,我想着写一个颜色的变化来练习一下,不想写了很长时间才写出来,跟各位分享一下. 颜色的变化是通过三元素渐变的方式完成的,通过构造json,使当前的颜色 ...
- 完美的js运动框架
//完美运动框架, 对象,json,函数function move(obj,json,funEnd){clearInterval(obj.timer);//清除定时器obj.timer= setInt ...
- js 运动框架-轻量级
具体代码如下: function move(obj,json,sv,fnEnd){ //CSS样式值 function getStyle(obj,attr){ if(obj.currentStyle) ...
随机推荐
- JAVA EE(简述)
一.平台概述 JavaEE的全称是Java Enterprise Edition,它是一个开发分布式企业级应用的规范和标准 Java 平台三个版本: Java ME(Java Micro Edit ...
- IOS Quartz2D 通过UIColor生成图片
普通生成 示例代码: //这里实现普通生成图片的方法 - (void)drawRect:(CGRect)rect { CGRect cxRect = CGRectMake(, , , ); UIGra ...
- C语言错误之--初始值(低级错误)
今天犯了一个低级错误,虽然低级,但是也不能忽视,一个低级错误以后可能小则浪费时间和精力,大则酿成整个app的项目bug.
- java基础--温故而知新 (01)
1 myeclipse是一个eclipse插件.使用java语言开发.进程是javaw.exe--非命令行方式启动. 2 考这些术语的公司,往往都是世界一流的好公司.(技术广度+英语) java ...
- FLUSH TABLES WITH READ LOCK
最近在mysql主从复制中用到锁,翻了资料回忆一下.一下内容参考于:http://blog.csdn.net/arkblue/article/details/27376991 1.FLUSH TABL ...
- Web Farm 和Web Garden
这两个都是提高网站性能的服务器端技术 1.Web Farm:如果应用程序被多个服务器托管,这种情况就可以称作Web Farm. 2.Web Garden: 指的是一个应用程序可以分成多个进程(w3wp ...
- Log4j配置与使用
log4j是Java社区事实上的日志标准解决方案.使用起来比较简单. 一. 简单使用 1.下载jar包放到lib文件夹,并加入到build path中: 2.编写log4j.properties文件, ...
- iOS -数据库网络之xml解析
XML文件有2种解析方式 1.基于文档(document) 2.基于事件(sax) 1.IOS中XML文件获取 首先要将XML导入工程中 在ViewController的按钮事件中,代码如下: ...
- Linux 安装 redis
环境:centos7 参考:http://blog.csdn.net/lk10207160511/article/details/50364088 步骤如下: 安装redis: 打开终端 输入 s ...
- 【C#】2.算法温故而知新 - 冒泡排序
冒泡排序可以很好的解决前面提到的简单桶排序的2个问题,冒泡排序的基本思想是:每次比较两个相邻的元素,如果它们的顺序错误就把它们交换过来. 该算法的核心部分是双重嵌套循环,其时间复杂度是O(N²). 缺 ...