动画的种类
动画原理 = 盒子位置 + 步长。
1.闪动。 (瞬间到达)
2.匀速。 (每次走一样距离)
3.缓动。 (开始特快越走越慢,步长越来越小.类似刹车,电梯停止,压缩弹簧…)
缓动动画原理
缓动动画原理: 盒子位置 + 步长(步长越来越小)
盒子位置 = 盒子本身位置+(目标位置-盒子本身位置)/ 10;
公式: leader = leader + (target - leader) / 10;
缓动动画用到的三个Math方法
Math.ceil(); 向上取整
Math.floor(); 向下取整
Math.round(); 四舍五入取整
0.缓动动画封装
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
}
</style>
<body>
<button>走到200</button>
<button>走到400</button>
<div></div>
<script>
//获取元素
var div = document.getElementsByTagName("div")[0];
var btnArr = document.getElementsByTagName("button");
//绑定事件
btnArr[0].onclick = function () {
//封装一个方法,调用这个函数。带两个参数。一个是盒子,一个是目标。
animate(div,20);
}
btnArr[1].onclick = function () {
animate(div,400);
}
//缓动动画封装
function animate(ele,target){
clearInterval(ele.timer);
ele.timer = setInterval(function () {
var leader = ele.offsetLeft;
var step = (target-leader)/10;
//二次处理步长:大于0向上取整,小于0向下取整
step = step>0 ?Math.ceil(step) :Math.floor(step);
ele.style.left = leader +step +"px";
if(Math.abs(target-leader)<Math.abs(step)){
ele.style.left = target +"px";
clearInterval(ele.timer);
}
},30);
}
</script>
/body>
1. 缓动框架封装(单个属性)
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
}
</style>
</head>
<body>
<button>动起来...</button>
<div></div>
<script>
var btn = document.getElementsByTagName("button")[0];
var box = document.getElementsByTagName("div")[0];
btn.onclick = function () {
animate(box,"top",400);
//animate(box,"width",400);
//animate(box,"height",400);
}
//缓动动画:(设置单个属性的值需要多出一个参数。属性)
function animate(ele,attr,target){
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//获取盒子自身的位置不能再用检测的方法了:offsetLeft;
//改用自己封装的获取样式的方法;既能获取内嵌式和行内式又可以获取外链式
var leader = parseInt(getStyle(ele,attr)) || 0;//带有单位,需要去掉px
//获取步长
var step = (target-leader)/10;
step = step>0?Math.ceil(step):Math.floor(step);
//赋值的时候要用传过来的属性
ele.style[attr] = leader + step +"px";
console.log(1);
if(Math.abs(target-leader)<=Math.abs(step)){
ele.style[attr] = target+"px";
clearInterval(ele.timer);
}
},30);
}
//封装一个兼容写法:
function getStyle(ele,attr){
//如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else{
return ele.currentStyle[attr];
}
}
</script>
/body>
2. 缓动框架封装(多个属性)利用json实现
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
/*margin-left: 100px;*/
}
</style>
</head>
<body>
<button>动起来...</button>
<div></div>
<script>
var btn = document.getElementsByTagName("button")[0];
var box = document.getElementsByTagName("div")[0];
btn.onclick = function () {
//缓动动画
var obj1 = {"left": 800, "top": 200, "width": 200, "height": 200};
animate(box, obj1);
}
function animate(ele, json) {
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//多个属性操作:很简单。
//1.利用for...in循环。
//2.把程序中的attr换成for...in中的k。
//3.把程序中的target换成for...in中的json[k]。
for (var k in json) {
var leader = parseInt(getStyle(ele, k)) || 0;//带有单位,需要去掉px
//获取步长
var step = (json[k] - leader) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
//赋值的时候要用传过来的属性
ele.style[k] = leader + step + "px";
console.log(1);
//定时器最难清除,一会儿再做。。。。
}
}, 30);
}
//封装一个兼容写法:
function getStyle(ele, attr) {
//如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
if (window.getComputedStyle) {
return window.getComputedStyle(ele, null)[attr];
} else {
return ele.currentStyle[attr];
}
}
</script>
</body>
3. 缓动框架封装(清除定时器)
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
}
</style>
</head>
<body>
<button>动起来</button>
<div></div>
<script>
var btn = document.getElementsByTagName("button")[0];
var box = document.getElementsByTagName("div")[0];
btn.onclick = function () {
var obj1 = {"left":800,"top": 200,"width":200,"height":200};
animate(box,obj1);
}
function animate(ele,json){
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//定义一个开闭原则
var bool = true;
for(var k in json){
var leader = parseInt(getStyle(ele,k)) || 0;//带有单位,需要去掉px
//获取步长
var step = (json[k]-leader)/10;
step = step>0?Math.ceil(step):Math.floor(step);
//赋值的时候要用传过来的属性
leader = leader + step;
ele.style[k] = leader +"px";
console.log(1);
//定时器最难清除,必须保证所有属性都到达指定位置,才能清除定时器
//再次启用开闭原则:有一个没有到达目标位置,也不能清除定时器
//if(Math.abs(json[k]-leader)>Math.abs(step)){
//没到达指定位置,就是当前位置和目标位置不相等
if(json[k]!=leader){
//不能清除定时器
bool = false;
}
}
//看看这个bool类型值是否被修改,如果是默认true代表所有元素都到达指定位置,就可以清除定时器了。
if(bool){
clearInterval(ele.timer);
}
},30);
}
//封装一个兼容写法:
function getStyle(ele,attr){
//如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else{
return ele.currentStyle[attr];
}
}
</script>
</body>
4. 缓动框架封装(回调函数)
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
/*margin-left: 100px;*/
}
</style>
</head>
<body>
<button>动起来...</button>
<div></div>
<script>
var btn = document.getElementsByTagName("button")[0];
var box = document.getElementsByTagName("div")[0];
btn.onclick = function () {
//缓动动画
var obj1 = {"left":400};
var obj2 = {"top":400};
//回调函数
animate(box,obj1, function () {
animate(box,obj2);
});
//走完第一个在走第二个:1.第一个定时器被清除的时候就可以走第二个函数来了。
}
//加一个fn,带表一个函数,当前一个定时器被清除的时候,在执行这个函数
function animate(ele,json,fn){
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//定义一个开闭原则
var bool = true;
for(var k in json){
var leader = parseInt(getStyle(ele,k)) || 0;//带有单位,需要去掉px
//获取步长
var step = (json[k]-leader)/10;
step = step>0?Math.ceil(step):Math.floor(step);
//赋值的时候要用传过来的属性
leader = leader + step;
ele.style[k] = leader +"px";
console.log(1);
//定时器最难清除,必须保证所有属性都到达指定位置,才能清除定时器
//再次启用开闭原则:有一个没有到达目标位置,也不能清除定时器
//没到达指定位置,就是当前位置和目标位置不相等
if(json[k]!=leader){
//不能清除定时器
bool = false;
}
}
//看看这个bool类型值是否被修改,如果是默认true代表所有元素都到达指定位置,就可以清除定时器了。
if(bool){
clearInterval(ele.timer);
//定时器被清除了,我可以执行fn这个函数了。
//判断:如果传递了函数就执行,如果没有传递,不管他
if(fn){//如果fn存在将代表函数体,如果不存在代表undefined
fn();
}
}
},30);
}
//封装一个兼容写法:
function getStyle(ele,attr){
//如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else{
return ele.currentStyle[attr];
}
}
</script>
</body>
5. 缓动框架封装(特殊属性处理透明度和层级)
<style>
*{
padding: 0;
margin: 0;
}
div {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
}
</style>
</head>
<body>
<button>动起来</button>
<div></div>
<script>
var btn = document.getElementsByTagName("button")[0];
var box = document.getElementsByTagName("div")[0];
btn.onclick = function () {
//缓动动画
// var obj1 = {"left":400};
var obj1 = {"opacity": 0.4};
// var obj1 = {"z-index": 2};
// var obj1 = {"background-color": "pink"};
//回调函数
//特殊属性特殊处理
animate(box,obj1);
}
function animate(ele,json,fn){
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//定义一个开闭原则
var bool = true;
for(var k in json){
//需求:特殊属性特殊处理。if判断如果是什么属性怎么处理,如果是另外一个属性,怎么处理....
//如果是层级,我们这么处理(k的值为z-index)
if("z-index" === k){
//层级不是缓慢移动到最高的,而是一次性提到最好。(需求决定)
//事件触发瞬间,层级立刻提高到最高,不能慢慢移动到最高。
ele.style.zIndex = json[k];
//如果是透明度我们这么处理
}else if("opacity" === k){
//问题1:透明度的值是小数,所以应该*100之后计算。(兼容IE678方便计算)
//问题2:透明度的兼容性不好。如果想要兼容IE678,要使用filter。(*100)
// 先获取透明度,然后*100在取整(小数精度丢失问题)。
// 如果没有给opacity属性,那么默认1,*100之后值为100;
var leader = parseInt(getStyle(ele,k)*100) || 100;
var step = (parseInt(json[k]*100)-leader)/10;
step = step>0?Math.ceil(step):Math.floor(step);
leader = leader + step;
//直接为opacity赋值,不需要加单位px;
//opacity要的是0-1之间的小数,所以除以100;
ele.style.opacity = leader/100;
//兼容ie678,不需要除以100,因为filter的值为100进制。
ele.style.filter = "alpha(opacity="+leader+")";
console.log(1);
if(parseInt(json[k]*100)!=leader){
//不能清除定时器
bool = false;
}
//普通属性普通处理
}else{
var leader = parseInt(getStyle(ele,k)) || 0;//带有单位,需要去掉px
var step = (json[k]-leader)/10;
step = step>0?Math.ceil(step):Math.floor(step);
leader = leader + step;
ele.style[k] = leader +"px";
console.log(1);
//if(Math.abs(json[k]-leader)<=Math.abs(step)){:对小数也可以赋值
if(json[k]!=leader){
//不能清除定时器
bool = false;
}
}
}
if(bool){
clearInterval(ele.timer);
if(fn){
fn();
}
}
},30);
}
//封装一个兼容写法:
function getStyle(ele,attr){
//如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}else{
return ele.currentStyle[attr];
}
}
</script>
</body>
案例
1.筋斗云
2.仿360开机页面
3.手风琴
4.旋转木马轮播图