js运动雏形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box{
width: 100px;
height: 100px;
background: #f00;
position: absolute;
left: 0;
top: 50px;
}
</style>
<script>
window.onload=function(){
var begin=document.getElementById("begin");
//上面获取begin应该和下面的方式一样,修改后可以显示,使用queryselectall不行
var stop=document.getElementById("stop");
var box=document.getElementById("box");
var timer;
//给开始按钮添加点击时间
begin.onclick=function(){
// 样式的结果带单位所以使用parseInt
var l= parseInt(getComputedStyle(box).left);
var t=parseInt(getComputedStyle(box).top);
var w=parseInt(getComputedStyle(box).width);
var h=parseInt(getComputedStyle(box).height);
// 30ms是电影换帧的参数,看电影最流畅。浏览器刷新频率或者电脑硬件都会影响反应时间。这里设置为16
timer=setInterval(function(){
l++;
t++;
w++;
h++;
box.style.left=l+'px';
box.style.top=t+'px';
box.style.width=w+'px';
box.style.height=h+'px';
},16);
// console.log(1);
stop.onclick=function(){
clearInterval(timer);
};
}
};
</script>
</head>
<body>
<input type="button" id="begin" value="开始">
<input type="button" id="stop" value="停止">
<div id="box"></div>
</body>
</html>
// 1.点击的时候需要getComputedStyle去获取到元素的属性值
// 2.点击开始按钮后开启一个重复执行定时器
// 3.在定时器里不断的修改元素的属性
QueryselectAll是静态获取,就是选出的元素不会随着文档的改变而变化
getElementById是动态获取,选的元素可以根据文档变化而变化
机械敲代码引发的低级 问题
运动的问题
运动的原理
在定时器里不断地去修改元素的属性,修改完成之后再把结果重新赋给元素
问题
1.如果每次的步长和目标值不成倍数,就到不了目标值
解决:把条件判断改成大于等于就可以
2.如果用户连续点击开始按钮,速度会越来越快
原因:用户不断点击开始按钮,会重复开启多个定时器造成速度累加
解决:再点击的时候先把上一个定时器清除。
<style>
#box{
width: 100px;
height: 100px;
background: #f00;
position: absolute;
left: 0;
top: 50px;
}
</style>
<script>
window.onload=function(){
var begin=document.getElementById("begin");
var box=document.getElementById("box");
var t;
begin.onclick=function(){
clearInterval(t); //2.清除一个不存在的定时器是不会有问题的,第二次点击就会清除第一次的定时器
// 开启定时器给t赋值
t=setInterval(function(){
var l=parseInt(getComputedStyle(box).left);
// l++,改成下面的代码会让方块运动加快,一次运动7px
l+=7;
// box走到300停下来
console.log(l);
if(l>=300){ //问题1
clearInterval(t);
// l=300;
}
box.style.left=l+"px";
},16);
};
}
</script>
3.如果有多个元素需要同时运动,那么前面的运动会没有效果
原因:因为每次运动开始都会清除上一个定时器,后面运动的时候清楚了前面的定时器,所以后面东前面不动了。
解决:使用自定义属性,只清除自己的定时器,不清楚别的定时器
<style>
#box1,#box2{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 50px;
}
#box2{
top: 200px;
}
</style>
<script>
window.onload=function(){
var btn=document.getElementById("btn");
var box1=document.getElementById("box1");
var box2=document.getElementById("box2");
var t;//所有元素共用一个定时器
function move(obj,attr,target){
// 清除定时器累加
// clearInterval(t);
clearInterval(obj.t);//一上来只清除自己的定时器不会清除别人的定时器
obj.t=setInterval(function(){
var value=parseInt(getComputedStyle(obj)[attr]);//获取到属性的值
value+=7;//让属性值不断+7
//如果属性值已经超过目标了,要定时清理定时器,同时为了避免越界,要把它拉回
if(value>=target){
clearInterval(t);
value=target;
}
//修改元素的属性值
obj.style[attr]=value+'px';
},16);
}
btn.onclick=function(){
move(box1,'left',300);
move(box2,'left',250);
}
}
</script>
<body>
<input type="button" id="btn" value="开始">
<div id="box1"></div>
<div id="box2"></div>
</body>
tip:两个物体运动不需要把代码写两份,封装函数即可
运动框架move.js
通过vscode终端命令引入move.js
运动的原理
限定时间的运动,根据时间去控制速度,已知时间和距离,计算速度
匀速运动
特点:在任何一个点的速度都是一样的
某个点的位置=速度x时间
速度=总距离/总时间
时间=现在的时间-开始的时间
某个点的位置=总的距离/总的时间*(现在的时间-开始的时间)
t已过的时间
b开始的时间
c总距离
d总时间
b是元素开始的位置,起点不一定在0,0,参数里的目标值是要运动到的那个点,而不是要走的距离。所以元素如果不在0,0开始运动的话,需要把起始点的距离加上。
var value=c/d*t+b
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload=function(){
var btn=document.getElementById("btn");
var box=document.getElementById("box");
btn.onclick=function(){
var c=300;
var d=2000;
var b=parseInt(getComputedStyle(box).left);
//一开始运动的时候要记录开始的时间
var startTime=new Date().getTime();
//开启定时器
var timer=setInterval(function(){
var t=new Date().getTime-startTime;
var value=c/d*t+b;
box.style.left=value+'px';
},16);
}
};
</script>
</head>
<body>
<input type="button" id="btn" value="开始">
<div id="box"></div>
</body>
</html>
运动框架的编写
下面的代码引用了Tween.js运动框架的js脚本,复制运行请自行添加。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 50px;
}
</style>
<script>
/*
obj运动的对象
attr 要运动的对象
target 要运动到的目标
duration要运动的时间
fx运动的形式
callBack运动完成之后调用的函数
*/
function move( obj,attr,target,duration,fx,callBack){
var d=duration;
//起始位置
var b=parseFloat(getComputedStyle(obj)[attr]) //attr是变量不是真正的属性所以使用中括号
var c=target-b;
var startTime=new Date().getTime();
clearInterval(obj.timer);
obj.timer=setInterval(function(){
var t=new Date.getTime()-startTime;
// 运动停止
if(t>=d){
t=d;
clearInterval(obj.timer);
}
//var value=c/d*t+b;
var value=Tween[fx](t,b,c,d);
obj.style[attr]=value+'px';
// 1
if(t==d){
if(callBack){
// 存在就调用
callBack();
}
}
// 2
if(t==d){
// 左真返回右,左假返回左,就什么都不做
callBack && callBack();
}
},16);
}
window.onload=function(){
var btn=document.getElementById("btn");
var box=document.getElementById("box");
btn.onclick=function(){
move(box,'left',400,1000,'linear',function(){
alert('运动完成了')
});
}
}
</script>
</head>
<body>
<input type="button" id="btn" value="开始">
<div id="box"></div>
</body>
</html>
也可以在运动完成了的方法内调用move
btn.onclick=function(){
// move(box,'left',400,1000,'linear',function(){
// alert('运动完成了')
// });
// 注意move函数的调用语法
move(box,'left',400,1000,'bounceIn');
}
move(obj,{left:10,top:20,opacity:0.8},duration,fx,callback)
只有callback不是必须的额
第二个参数里面用的键值对的形式,值没有单位,opacity的值是0-1