JavaScript进阶【五】利用JavaScript实现动画的基本思路
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#div {
width: 100px;
height: 100px;
background-color: #00a8c6;
position: absolute;
} #block {
width: 80px;
height: 80px;
background-color: #0a001f;
position: absolute;
margin-left: 120px;
} #blockTwo {
width: 80px;
height: 80px;
background-color: #00FA9A;
position: absolute;
margin-left: 190px;
} #ball {
width: 100px;
height: 100px;
border-radius: 50px;
border: solid rgb(100, 100, 100) 1px;
position: absolute;
margin-top: 100px;
background-color: #1b1b1b;
} #car {
width: 80px;
height: 80px;
background-color: #4B0082;
position: absolute;
margin-left: 220px;
} #stone {
width: 50px;
height: 50px;
border-radius: 25px;
border: solid rgb(100, 100, 100) 1px;
position: absolute;
margin-top: 150px;
margin-left: 150px;
background-color: #8B0000;
} #SinMove {
width: 50px;
height: 50px;
border-radius: 25px;
border: solid rgb(100, 100, 100) 1px;
position: absolute;
margin-top: 800px;
margin-left: 220px;
background-color: #00FA9A;
} #CircleMove {
width: 50px;
height: 50px;
background-color: #4B0082;
margin-top: 500px;
margin-left: 500px;
} #moveAny {
width: 100px;
height: 100px;
border-radius: 50px;
border: solid rgb(100, 100, 100) 1px;
position: absolute;
margin-top: 800px;
margin-left: 220px;
background-color: #7FFF00;
text-align: center;
padding-top: 20px;
} #controlPan {
margin-top: 400px;
border: 2px solid blue;
height: 400px;
width: auto;
}
</style> <!--1.实现一个简单的div块元素-->
<script>
var id; var direct = -1;
var times = 0; function step() {
times++; // 获取这个块元素
var div = document.getElementById("div"); console.log(div.offsetLeft);
if (div.offsetLeft == 800) {
direct = 0;
} else if (div.offsetLeft == 8) {
direct = 1;
} if (direct == 1) {
// 设置这个div元素向左的偏移量
var temp = div.offsetLeft + 2;
// 设置坐标的距离
div.style.left = temp + "px";
} else if (direct == 0) {
// 设置这个div元素向左的偏移量
var temp = div.offsetLeft - 2;
// 设置坐标的距离
div.style.left = temp + "px";
} //和setTimeout一样,要手动调用才能实现连续动画。
id = window.requestAnimationFrame(step); //返回值是一个id,可以通过这个id来取消 // 复杂的计算
for (var i = 0; i < 50; i++) {
console.log("再牛逼的定时器也得等到我执行完才能执行");
} //取消回调函数
if (times == 0) {
window.cancelAnimationFrame(id);
} } // 第一次调用
//id = window.requestAnimationFrame(step); </script> <!--2.setTimeout和setInterval深入理解-->
<script>
/*console.log("1");
setTimeout(function () {
console.log("3");
}, 0);
console.log("2"); // 输出: 1 2 3*/
// 2. 使用动画的正确姿势,动画其实是 “位移”关于“时间”的函数:s=f(t)
// 解决动画变慢的问题:把动画与时间关联起来
function startAnimation() {
var startTime = Date.now();
requestAnimationFrame(function change(time) {
var current = Date.now() - startTime;
console.log("动画已经执行的时间为:" + current);
requestAnimationFrame(startAnimation);
});
} //startAnimation(); // 动画通常情况下有终止时间,如果是循环动画,我们也可以看做特殊的——当动画达到终止时间之后,重新开始动画。因此,我们可以将动画时间归一(Normalize)表示:
//duration 是动画执行时间 isLoop是否为循环执行。
function startAnimation(duration, isLoop) {
var startTime = Date.now(); requestAnimationFrame(function change() {
// 动画已经用去的时间占总时间的比值
var p = (Date.now() - startTime) / duration;
//console.log(p); if (p >= 1.0) {
if (isLoop) { // 如果是循环执行,则开启下一个循环周期。并且把开始时间改成上个周期的结束时间
startTime += duration;
p -= 1.0; //动画进度初始化
} else {
p = 1.0; //如果不是循环,则把时间进度至为 1.0 表示动画执行结束
}
}
console.log("动画已执行进度", p);
if (p < 1.0) { //如果小于1.0表示动画还诶有值完毕,继续执行动画。
requestAnimationFrame(change);
}
});
} //startAnimation(100, true); // 示例1:用时间控制动画周期精确到2s中
function blockClick(obj) {
var block = document.getElementById("block"); var self = obj,
startTime = Date.now(),
duration = 2000;
// 添加一个动画
setInterval(function () {
var p = (Date.now() - startTime) / duration;
// 时间已经完成了2000的比例,则360度也是进行了这么个比例。
self.style.transform = "rotate(" + (360 * p) + "deg)";
}, 100); } // 示例2:让滑块在2秒内向右匀速移动600px
function blockTwoClick(obj) {
var self = obj;
var startTime = Date.now(),
distance = 600,
duration = 2000; requestAnimationFrame(function step(time) {
var p = Math.min(1.0, (Date.now() - startTime) / duration);
//沿着X方向运动
self.style.transform = "translateX(" + (distance * p) + "px)";
// 如果动画没有执行完毕, 就继续执行
if (p < 1.0) {
requestAnimationFrame(step);
}
})
}; // 实例3: 实现小球的自由落体运动
function ballClick(obj) {
var self = obj,
startTime = Date.now(),
distance = 1000,
duration = 1500;
requestAnimationFrame(function step() {
var p = Math.min(1.0, (Date.now() - startTime) / duration);
self.style.transform = "translateY(" + (distance * p * p) + "px)";
if (p < 1.0) requestAnimationFrame(step);
}); } // 实例4 : 实现汽车的匀减速运动
function carClick(obj) {
var self = obj, startTime = Date.now(),
distance = 1000, duration = 2000;
requestAnimationFrame(function step() {
var p = Math.min(1.0, (Date.now() - startTime) / duration);
self.style.transform = "translateX("
+ (distance * p * (2 - p)) + "px)";
if (p < 1.0) requestAnimationFrame(step);
}); } // 实例5 : 水平抛物运动
function stoneClick(obj) {
var self = obj, startTime = Date.now(),
disX = 1000, disY = 1000,
duration = Math.sqrt(2 * disY / 10 / 9.8) * 1000; // 落到地面需要的时间 单位ms
//假设10px是1米,disY = 100米 requestAnimationFrame(function step() {
var p = Math.min(1.0, (Date.now() - startTime) / duration);
var tx = disX * p; //水平方向是匀速运动
var ty = disY * p * p; //垂直方向是匀加速运动 self.style.transform = "translate("
+ tx + "px" + "," + ty + "px)";
if (p < 1.0) requestAnimationFrame(step);
}); } // 实例6 : 正弦曲线运动
function SinMoveClick(obj) {
var self = obj, startTime = Date.now(),
distance = 800,
duration = 5000; requestAnimationFrame(function step() {
var p = Math.min(1.0, (Date.now() - startTime) / duration);
var ty = distance * Math.sin(2 * Math.PI * p);
var tx = 2 * distance * p; self.style.transform = "translate("
+ tx + "px," + ty + "px)";
if (p < 1.0) requestAnimationFrame(step);
}); } // 实例7 : 圆周运动
function CircleMoveClick(obj) {
var self = obj,
startTime = Date.now(),
r = 100,
duration = 2000; requestAnimationFrame(function step() {
var p = Math.min(1.0, (Date.now() - startTime) / duration);
var tx = r * Math.sin(2 * Math.PI * p),
ty = -r * Math.cos(2 * Math.PI * p); self.style.transform = "translate(" +
tx + "px," + ty + "px)";
requestAnimationFrame(step);
});
} // 实现动画算子的封装
// pow() 方法可返回 x 的 y 次幂的值
var pow = Math.pow,
BACK_CONST = 1.70158;
// t指的的是动画进度 前面的p
Easing = {
// 匀速运动
linear: function (t) {
return t;
},
// 加速运动
easeIn: function (t) {
return t * t;
},
// 减速运动
easeOut: function (t) {
return (2 - t) * t;
},
//先加速后减速
easeBoth: function (t) {
return (t *= 2) < 1 ? .5 * t * t : .5 * (1 - (--t) * (t - 2));
},
// 4次方加速
easeInStrong: function (t) {
return t * t * t * t;
},
// 4次方法的减速
easeOutStrong: function (t) {
return 1 - (--t) * t * t * t;
},
// 先加速后减速,加速和减速的都比较剧烈
easeBothStrong: function (t) {
return (t *= 2) < 1 ? .5 * t * t * t * t : .5 * (2 - (t -= 2) * t * t * t);
},
//
easeOutQuart: function (t) {
return -(Math.pow((t - 1), 4) - 1)
},
// 指数变化 加减速
easeInOutExpo: function (t) {
if (t === 0) return 0;
if (t === 1) return 1;
if ((t /= 0.5) < 1) return 0.5 * Math.pow(2, 10 * (t - 1));
return 0.5 * (-Math.pow(2, -10 * --t) + 2);
},
//指数式减速
easeOutExpo: function (t) {
return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1;
},
// 先回弹,再加速
swingFrom: function (t) {
return t * t * ((BACK_CONST + 1) * t - BACK_CONST);
}, // 多走一段,再慢慢的回弹
swingTo: function (t) {
return (t -= 1) * t * ((BACK_CONST + 1) * t + BACK_CONST) + 1;
}, //弹跳
bounce: function (t) {
var s = 7.5625,
r; if (t < (1 / 2.75)) {
r = s * t * t;
} else if (t < (2 / 2.75)) {
r = s * (t -= (1.5 / 2.75)) * t + .75;
} else if (t < (2.5 / 2.75)) {
r = s * (t -= (2.25 / 2.75)) * t + .9375;
} else {
r = s * (t -= (2.625 / 2.75)) * t + .984375;
} return r;
}
}; /*
参数1:动画的执行时间
参数2:动画执行的时候的回调函数(动画执行的要干的事情)
参数3:动画算子. 如果没有传入动画算子,则默认使用匀速算子
*/
function Animator(duration, progress, easing) {
this.duration = duration;
this.progress = progress;
this.easing = easing || function (p) {
return p
};
} Animator.prototype = {
/*开始动画的方法,
参数:一个布尔值
true表示动画不循环执行。
*/
start: function (finished) {
/*动画开始时间*/
var startTime = Date.now();
/*动画执行时间*/
var duration = this.duration,
self = this;
/*定义动画执行函数*/
requestAnimationFrame(function step() {
/*得到动画执行进度*/
var p = (Date.now() - startTime) / duration;
/*是否执行下一帧动画*/
var next = true;
/*判断动画进度是否完成*/
if (p < 1.0) {
self.progress(self.easing(p), p); //执行动画回调函数,并传入动画算子的结果和动画进度。
} else {
if (finished) { //判断是否停止动画。如果是true代表停止动画。
next = false;
} else {
startTime = Date.now();
}
}
// 如果next是true执行下一帧动画
if (next) requestAnimationFrame(step);
});
}
}; function ChangeState() {
var self = document.getElementById("moveAny");
// 新建一个动画
new Animator(2000, function (p) {
self.style.top = 500 * p + "px";
}, Easing.easeBoth).start(false); } </script>
</head>
<body>
<div style="border: 2px solid red">
<!--动画实现方式:通过操作JavaScript间接操作CSS样式,每隔一段时间更新一次;-->
<div id="div"></div> <div id="block" onclick="blockClick(this)"></div>
<div id="blockTwo" onclick="blockTwoClick(this)"></div> <div id="ball" onclick="ballClick(this)"></div>
<div id="car" onclick="carClick(this)"></div>
<div id="stone" onclick="stoneClick(this)"></div>
<div id="SinMove" onclick="SinMoveClick(this)"></div>
<div id="CircleMove" onclick="CircleMoveClick(this)"></div>
</div> <div id="moveAny">我是一个可以做任意运动的物体</div>
<div id="controlPan">控制面板
<button onclick="ChangeState(this)">切换运动状态</button>
</div>
</body>
</html>
JavaScript进阶【五】利用JavaScript实现动画的基本思路的更多相关文章
- JavaScript进阶(五)js中取小数整数部分函数
js中取小数整数部分函数 丢弃小数部分,保留整数部分 js:parseInt(7/2) 向上取整,有小数就整数部分加1 js: Math.ceil(7/2) 四舍五入 js: Math.round(7 ...
- JavaScript 进阶教程一 JavaScript 中的事件流 - 事件冒泡和事件捕获
先看下面的示例代码: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Jav ...
- JavaScript进阶(六)用JavaScript读取和保存文件
用JavaScript读取和保存文件 因为Google还不提供同步插件数据的功能,所以导入和导出插件配置就必须和文件打交道了.而出于安全原因,只有IE才提供访问文件的API:但随着HTML 5的到来, ...
- javascript进阶修炼之一——javascript必备操做
动态选择方法及属性 使用方括号操作符,比点操作符功能更强大.因为可以在[ ]方括号中使用任何代表成员名称的内容访问对象.包括字面量,保存着成员名称的变量,名称组合,三元操作符.所有这些内容都会被处理成 ...
- 4、JavaScript进阶篇①——基础语法
一.认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂亮的页面,但这还不够,它只是静态页面 ...
- JavaScript进阶内容——jQuery
JavaScript进阶内容--jQuery 我们在前面的文章中已经掌握了JavaScript的全部内容,现在让我们了解一下JavaScript库 这篇文章主要是为了为大家大致讲解JavaScript ...
- 利用javascript和WebGL绘制地球 【翻译】
利用javascript和WebGL绘制地球 [翻译] 原翻译:利用javascript和WebGL绘制地球 [翻译] 在我们所有已知的HTML5API中,WebGL可能是最有意思的一个,利用这个AP ...
- JavaScript进阶学习的一些建议
blankyao最近问我如何学习JavaScript,他觉着在理解了JavaScript的语法之后,不知如何去学习JavaScript了. 其实我也是个JavaScript小菜,最近在开发中遇到不少关 ...
- JavaScript进阶(三)
现在来说说判断语句(if)if语句是基于条件成立才执行相应代码时使用的语句.语法:if(条件){条件成立时执行代码}注意:if小写,大写字母(IF)会出错!假设你应聘web前端技术开发岗位,如果你会h ...
- Javascript 进阶 面向对象编程 继承的一个样例
Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承.这篇使用一个样例来展示js怎样面向对象编程.以及怎样基于类实现继承. 1. ...
随机推荐
- logstash-input-jdbc实现mysql 与elasticsearch实时同步(ES与关系型数据库同步)
引言: elasticsearch 的出现使得我们的存储.检索数据更快捷.方便.但很多情况下,我们的需求是:现在的数据存储在mysql.oracle等关系型传统数据库中,如何尽量不改变原有数据库表结构 ...
- POJ 2375
BFS+强连通.输出max(缩点后出度为0的点数,缩点后入度为0的点数). #include <cstdio> #include <iostream> #include < ...
- jQuery学习之开篇
吐槽 近期比較烦,对于一个前端白痴来说,工作方向突然转向前端这块着实让人蛋疼无比.前段时间简单的学习了下EasyUI,算是对其有一个简单的认知了吧.EasyUI的研究过程中发现,假设没有掌握JS.JQ ...
- 【传智播客VIP用户专享】Swift教程最新更新
(1)[传智播客VIP用户专享]Swift教程最新更新 特地贡献出来忘帮顶!!(传智内部学院给的) http://pan.baidu.com/s/1jGmRRIu 提取码:i11g 相关资料下载 ...
- Activiti的简单入门样例(经典的请假样例)
经典的请假样例: 流程例如以下,首先须要部门经理审批.假设请假天数大于2天,则须要总经理审批,否则HR审批就可以 一:创建maven项目,项目结构例如以下: watermark/2/text/aHR0 ...
- Mysql经常使用函数汇总
一. 聚合函数 1.1 求和函数-----SUM() 求和函数SUM( )用于对数据求和.返回选取结果集中全部值的总和. 语法:SELECT SUM(column_name) FROM table_n ...
- 基于Torndb的简易ORM
============================================================================ 原创作品,同意转载. 转载时请务必以超链接形式 ...
- 利用GDAL实现影像的几何校正
一.概述 遥感影像和地理坐标进行关联的方式一般有好几种,一种是直接给出了仿射变换系数,即6个參数,左上角地理坐标,纵横方向上的分辨率,以及旋转系数.在这样的情况下,求出某一像素点的地理坐标非常easy ...
- yolo源码解析(3):进行简单跳帧
视频检测命令 ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights ../../dataset/ ...
- libhiredis.so.0.13 => not found 缺少
wget https://github.com/redis/hiredis/archive/v0.13.3.tar.gz tar -xzvf v0.13.3.tar.gz cd hiredis- ma ...