目录
运动与游戏开发
认识运动
动画:图像
原理:人眼能够识别的最小的时间间隔是18帧
实现动画:只需要让动画的切换时间间隔大于18帧,一般情况下,电影院里放映的电影是24帧
简单的运动:
让一个div从左向右开始运动
<!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>
*{margin: 0px; padding: 0px;}
#div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 0px; top: 100px;}
</style>
<script>
/*
问题:
1、停不下来
2、当速度取某些值得时候停不下来
3、到达目的值以后,点击还会继续往前运动
if...else 将运动和停止分开
4、重复点击按钮,速度加快
保证只有一个定时器
每次启动定时器之前,先将上一次定时器关闭
*/
/*
运动框架:
1、每次启动定时器之前,先将上一次定时器关闭
2、if...else 将运动和停止分开
*/
window.onload = function(){
var oBtn = document.getElementById("btn1");
var oDiv = document.getElementById("div1");
var speed = 7;
var timer = null;
oBtn.onclick = function(){
clearInterval(timer);
timer = setInterval(function(){
if(oDiv.offsetLeft >= 500){
clearInterval(timer);
}else{
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
}
}, 30);
}
}
</script>
</head>
<body>
<button id="btn1">开始运动</button>
<div id="div1"></div>
</body>
</html>
分享到菜单案例
<!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>
#div1{width: 100px; height: 200px; background-color: gray; position: absolute; left: -100px; top: 400px;}
#div1 span{width: 20px; height: 60px; background-color: orange; position: absolute; left: 100px; top: 70px; line-height: 20px;}
</style>
<script>
/*
鼠标移入:left从 -100 => 0
鼠标移出:left从 0 => -100
*/
window.onload = function(){
var oDiv = document.getElementById("div1");
oDiv.onmouseover = function(){
startMove(5, 0);
}
oDiv.onmouseout = function(){
startMove(-5, -100);
}
}
var timer = null;
function startMove(speed, iTarget){
var oDiv = document.getElementById("div1");
clearInterval(timer);
timer = setInterval(function(){
//将运动停止和分开
if(oDiv.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
}
}, 30);
}
/* function startMove2(){
var oDiv = document.getElementById("div1");
var speed = -5;
clearInterval(timer);
timer = setInterval(function(){
//将运动停止和分开
if(oDiv.offsetLeft == -100){
clearInterval(timer);
}else{
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
}
}, 30);
} */
</script>
</head>
<body>
<div id="div1">
<span>分享到</span>
</div>
</body>
</html>
改进1:
window.onload = function(){
var oDiv = document.getElementById("div1");
oDiv.onmouseover = function(){
startMove(0);
}
oDiv.onmouseout = function(){
startMove(-100);
}
}
var timer = null;
function startMove(iTarget){
var oDiv = document.getElementById("div1");
var speed = 5;
if(oDiv.offsetLeft > iTarget){
speed = -Math.abs(speed);
}else{
speed = Math.abs(speed);
}
clearInterval(timer);
timer = setInterval(function(){
//将运动停止和分开
if(oDiv.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
}
}, 30);
}
淡入淡出案例
<!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>
#img1{opacity: 0.3; filter: alpha(opacity = 30); }
</style>
<script>
window.onload = function(){
var oImg = document.getElementById("img1");
oImg.onmouseover = function(){
//透明度由 30 --> 100
startMove(100);
}
oImg.onmouseout = function(){
//透明度由 100 --> 30
startMove(30);
}
}
//设置一个中间变量,透明度当前值
var alpha = 30;
var timer = null;
function startMove(iTarget){
var oImg = document.getElementById("img1");
clearInterval(timer);
var speed = 2;
speed = iTarget > alpha ? Math.abs(speed) : -Math.abs(speed);
timer = setInterval(function(){
if(iTarget == alpha){
clearInterval(timer);
}else{
alpha += speed;
//重新设置透明度
oImg.style.opacity = alpha / 100;
oImg.style.filter = `alpha(opacity=${alpha})`;
}
//document.title = alpha; /* 通过title上的数值检查alpha是否复合我们的预期 */
}, 30);
}
</script>
</head>
<body>
<img id="img1" src="./images/sxx1.jpg" style="width: 405px; height: 270px;">
</body>
</html>
缓冲运动
<!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>
*{margin: 0px; padding: 0px;}
#div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 0px; top: 200px; }
</style>
<script>
/*
刹车
不是物理规律的特点:速度和距离成正相关
var speed = 距离
var speed = (iTarget - iCur) / 8;
*/
window.onload = function(){
var oBtn = document.getElementById("btn1");
var oDiv1 = document.getElementById("div1");
oBtn.onclick = function(){
startMove(500);
}
}
var timer = null;
function startMove(iTarget){
var oDiv1 = document.getElementById("div1");
clearInterval(timer);
timer = setInterval(function(){
var speed = (iTarget - oDiv1.offsetLeft) / 8;//速度和距离公式
if(oDiv1.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv1.style.left = oDiv1.offsetLeft + speed + 'px';
}
},30);
}
</script>
</head>
<body>
<button id="btn1">开始运动</button>
<div id="div1"></div>
</body>
</html>
当我们添加一个speed = 500时的标志,我们会发现红色方块无法完全贴合次标志
<!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>
*{margin: 0px; padding: 0px;}
#div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 0px; top: 200px; }
</style>
<script>
/*
刹车
不是物理规律的特点:速度和距离成正相关
var speed = 距离
var speed = (iTarget - iCur) / 8;
*/
window.onload = function(){
var oBtn = document.getElementById("btn1");
var oDiv1 = document.getElementById("div1");
oBtn.onclick = function(){
startMove(500);
}
}
var timer = null;
function startMove(iTarget){
var oDiv1 = document.getElementById("div1");
clearInterval(timer);
timer = setInterval(function(){
var speed = (iTarget - oDiv1.offsetLeft) / 8;//速度和距离公式
if(oDiv1.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv1.style.left = oDiv1.offsetLeft + speed + 'px';
}
},30);
}
</script>
</head>
<body>
<button id="btn1">开始运动</button>
<div id="div1"></div>
<span style="width: 1px; height: 500px; background-color: black; position: absolute; left: 500px;"></span>
</body>
</html>
修改版:
<!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>
*{margin: 0px; padding: 0px;}
#div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 1000px; top: 200px; }
</style>
<script>
/*
刹车
不是物理规律的特点:速度和距离成正相关
var speed = 距离
var speed = (iTarget - iCur) / 8;
【注】计算机最小能识别的像素时一像素
*/
window.onload = function(){
var oBtn = document.getElementById("btn1");
var oDiv1 = document.getElementById("div1");
oBtn.onclick = function(){
startMove(500);
}
}
var timer = null;
function startMove(iTarget){
var oDiv1 = document.getElementById("div1");
clearInterval(timer);
timer = setInterval(function(){
var speed = (iTarget - oDiv1.offsetLeft) / 8;//速度和距离公式
/* speed = Math.ceil(speed);//向上取整;但是对于反向缓冲运动来说,此方法无法解决此问题 */
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(oDiv1.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv1.style.left = oDiv1.offsetLeft + speed + 'px';
}
var oTxt1 = document.getElementById("txt1");
oTxt1.value += speed + ',' + oDiv1.offsetLeft + '\n'
},30);
}
</script>
</head>
<body>
<button id="btn1">开始运动</button>
<div id="div1"></div>
<textarea name="" id="txt1" cols="30" rows="10"></textarea>
<span style="width: 1px; height: 500px; background-color: black; position: absolute; left: 500px;"></span>
</body>
</html>
缓冲运动案例
1、匀速运动
<1>每次启动定时器,关闭上一次定时器
<2>if...else将运动和停止分开
2、分享到菜单 淡入淡出效果(alpha)
startMove(iTarget);
3、缓冲运动
var speed = (iTarget - iCur) / 8;(经过长期实验÷8动画最明显,iCur为当前位置)
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
缓冲运动实现的缓冲菜单:
<!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>
*{margin: 0px; padding: 0px;}
#div1{width: 50px; height: 50px; background-color: red; position: absolute; right: 0px;}
</style>
<script>
window.onload = function(){
var oDiv = document.getElementById("div1");
//获取居中的top值
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //获取滚动了的高度
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight; //获取可视窗口的高度
var iH = parseInt(scrollTop + (windowHeight - oDiv.offsetHeight) / 2); //top居中值
startMove(iH);
//窗口滚动时,红色方块也靠右居中
window.onscroll = function(){
//获取居中的top值
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //获取滚动了的高度
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight; //获取可视窗口的高度
var iH = parseInt(scrollTop + (windowHeight - oDiv.offsetHeight) / 2); //top居中值
startMove(iH);
}
//窗口放大缩小时,红色方块也靠右居中
window.onresize = function(){
//获取居中的top值
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //获取滚动了的高度
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight; //获取可视窗口的高度
var iH = parseInt(scrollTop + (windowHeight - oDiv.offsetHeight) / 2); //top居中值
startMove(iH);
}
}
var timer = null;
function startMove(iTarget){
var oDiv = document.getElementById("div1");
clearInterval(timer);
timer = setInterval(function(){
//计算速度
var speed = (iTarget - oDiv.offsetTop) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(oDiv.offsetTop == iTarget){
clearInterval(timer);
}else{
oDiv.style.top = oDiv.offsetTop + speed + 'px';
}
document.title = oDiv.offsetTop + ',' + iTarget; //测试
}, 30);
}
</script>
</head>
<body style="height: 3000px;">
<div id="div1"></div>
</body>
</html>
多物体运动
<!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>
div{width: 100px; height: 50px; background-color: red; margin: 100px;}
</style>
<script>
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
for(var i = 0; i < aDivs.length; i++){
aDivs[i].onmousemove = function(){
startMove(this, 300);
}
aDivs[i].onmouseout = function(){
startMove(this, 100);
}
}
}
/* 让谁进行运动不确定,增加一个node参数
多物体运动,但实际上只有一个定时器
让每一个运动的物体都有一个定时器,
*/
var timer = null;
function startMove(node, iTarget){
clearInterval(timer);
timer = setInterval(function(){
var speed = (iTarget - node.offsetWidth) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(node.offsetWidth == iTarget){
clearInterval(timer);
}else{
node.style.width = node.offsetWidth + speed + 'px';
}
}, 30);
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>
出现的问题:当移入其中一个div后快速移入另一个div中,上一个动画被关闭,无法还原
修改版:
<!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>
div{width: 100px; height: 50px; background-color: red; margin: 100px;}
</style>
<script>
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
for(var i = 0; i < aDivs.length; i++){
aDivs[i].onmouseover = function(){
startMove(this, 300);
}
aDivs[i].onmouseout = function(){
startMove(this, 100);
}
}
}
/* 让谁进行运动不确定,增加一个node参数
多物体运动,但实际上只有一个定时器
让每一个运动的物体都有一个定时器,
*/
/* var timer = null; */
function startMove(node, iTarget){
clearInterval(node.timer);
node.timer = setInterval(function(){
var speed = (iTarget - node.offsetWidth) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(node.offsetWidth == iTarget){
clearInterval(node.timer);
}else{
node.style.width = node.offsetWidth + speed + 'px';
}
}, 30);
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>
添加淡入淡出效果:
<!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>
div{width: 100px; height: 50px; background-color: red; margin: 100px; opacity: 0.3; filter: alpha(opacity=30);}
</style>
<script>
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
for(var i = 0; i < aDivs.length; i++){
aDivs[i].alpha = 30;
aDivs[i].onmouseover = function(){
startMove(this, 100);
}
aDivs[i].onmouseout = function(){
startMove(this, 30);
}
}
}
// var alpha = 30;
/*
在多物体运动中:
1、定时器不可共用
2、任何数据都不能共用
*/
function startMove(node,iTarget){
clearInterval(node.timer);
node.timer = setInterval(function(){
var speed = (iTarget - node.alpha) / 30;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(iTarget == node.alpha){
clearInterval(node.timer);
}else{
node.alpha += speed;
node.style.opacity = node.alpha / 100;
node.style.filter = "alpha(opacity=" + node.alpha + ")";
}
},30);
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
</body>
</html>
多物体多样式运动
<!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>
#div1{width: 200px; height: 100px; background-color: red; border: 1px solid black;}
</style>
<script>
/*
每隔30ms width-1
加上border后,width+1; 原因是offsetWidth获取的不仅仅是width还会加上border
*/
window.onload = function(){
var oDiv = document.getElementById("div1");
setInterval(function(){
alert(oDiv.offsetWidth); //获取width + border
oDiv.style.width = oDiv.offsetWidth - 1 + 'px';
},30);
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
解决加上border后width变为width+1问题:
<!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>
#div1{width: 200px; height: 100px; background-color: red; border: 1px solid black;}
</style>
<script>
/*
实现运动的函数里面,都用getStyle方法来获取当前有效样式
*/
window.onload = function(){
var oDiv = document.getElementById("div1");
setInterval(function(){
//获取当前值
var iCur = parseInt(getStyle(oDiv,"width"));
alert(iCur);
oDiv.style.width = iCur - 1 + 'px';
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
多物体多样式的运动:
<!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>
div{width: 100px; height: 100px; background-color: red; margin: 50px;}
</style>
<script>
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
aDivs[0].onclick = function(){
//宽变为300px
startMove(this, "width", 300);
}
aDivs[1].onclick = function(){
//高变为300px
startMove(this, "height", 300);
}
aDivs[2].onclick = function(){
//margin-left变为300px
startMove(this, "margin-left", 300);
}
aDivs[3].onclick = function(){
//font-size变为100px
startMove(this, "font-size", 100);
}
}
function startMove(node, attr, iTarget){
clearInterval(node.timer);
node.timer = setInterval(function(){
//计算速度
var iCur = parseInt(getStyle(node,attr));
var speed = (iTarget - iCur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(iCur == iTarget){
clearInterval(node.timer);
}else{
node.style[attr] = iCur + speed + 'px'; //没有attr这个样式,所以需要用'[ ]'获取attr
}
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div>div文本</div>
</body>
</html>
缺点:只能解决带px的样式
如果要添加透明度操作:
<!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>
div{width: 100px; height: 100px; background-color: red; margin: 50px; opacity: 0.3; filter: alpha(opacity=30);}
</style>
<script>
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
aDivs[0].onclick = function(){
//宽变为300px
startMove(this, "width", 300);
}
aDivs[1].onclick = function(){
//高变为300px
startMove(this, "height", 300);
}
aDivs[2].onclick = function(){
//margin-left变为300px
startMove(this, "margin-left", 300);
}
aDivs[3].onclick = function(){
//font-size变为100px
startMove(this, "font-size", 100);
}
aDivs[4].onmouseover = function(){
startMove(this, "opacity", 100);
}
aDivs[4].onmouseout = function(){
startMove(this, "opacity", 30);
}
}
function startMove(node, attr, iTarget){
clearInterval(node.timer);
node.timer = setInterval(function(){
//计算速度
var iCur = null;
if(attr == 'opacity'){
iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
}else{
iCur = parseInt(getStyle(node,attr));
}
var speed = (iTarget - iCur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(iCur == iTarget){
clearInterval(node.timer);
}else{
if(attr == "opacity"){
iCur += speed;
node.style.opacity = iCur / 100;
node.style.filter = "alpha(opacity" + iCur + ")";
}else{
node.style[attr] = iCur + speed + 'px';
}
}
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div>div文本</div>
<div></div>
</body>
</html>
链式运动
链式运动概念
在第一个动画结束的时候,开始第二个动画
【注】关键点,找到第一个动画结束的时候
回调函数:我们把函数当作参数传入,并且在合适的地方调用,叫做回调函数。在别的编程语言(C语言、C++)叫做函数指针。
<!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>
div{width: 100px; height: 100px; background-color: red; margin: 50px; opacity: 0.3; filter: alpha(opacity=30);}
</style>
<script>
/*
希望实现三个动画,且为链式进行
*/
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
aDivs[0].onclick = function(){
startMove(this, "width", 300, show);
}
function show(){
alert(this); //指向当前的div
alert("运动结束了");
}
}
function startMove(node, attr, iTarget, complete){ //complete = show;
clearInterval(node.timer);
node.timer = setInterval(function(){
//计算速度
var iCur = null;
if(attr == 'opacity'){
iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
}else{
iCur = parseInt(getStyle(node,attr));
}
var speed = (iTarget - iCur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(iCur == iTarget){
clearInterval(node.timer);
if(complete){
// complete(); //为了使后续代码调用方便,将show函数的指向强制改变
complete.call(node);
}
/* 第一次运动结束的点 */
// alert("运动结束");
/*
当运动结束以后,应该做什么的代码在这里不能写死。
【注】封装函数,形参,根据汉书不确定的值决定的
可以将一段代码编写的权力交给别人,在函数上声明一个形参,这个形参是用来接收从外面封装好的一个函数的。
*/
}else{
if(attr == "opacity"){
iCur += speed;
node.style.opacity = iCur / 100;
node.style.filter = "alpha(opacity" + iCur + ")";
}else{
node.style[attr] = iCur + speed + 'px';
}
}
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div></div>
</body>
</html>
修改后:
<!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>
div{width: 100px; height: 100px; background-color: red; margin: 50px; opacity: 0.3; filter: alpha(opacity=30);}
</style>
<script>
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
aDivs[0].onmouseover = function(){
startMove(this, "width", 300, function(){
startMove(this, "height" ,300, function(){
startMove(this, "opacity", 100);
});
});
}
aDivs[0].onmouseout = function(){
startMove(this, "opacity", 30, function(){
startMove(this, "width", 100, function(){
startMove(this, "height", 100);
});
});
}
}
function startMove(node, attr, iTarget, complete){
clearInterval(node.timer);
node.timer = setInterval(function(){
//计算速度
var iCur = null;
if(attr == 'opacity'){
iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
}else{
iCur = parseInt(getStyle(node,attr));
}
var speed = (iTarget - iCur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(iCur == iTarget){
clearInterval(node.timer);
if(complete){
complete.call(node);
}
}else{
if(attr == "opacity"){
iCur += speed;
node.style.opacity = iCur / 100;
node.style.filter = "alpha(opacity" + iCur + ")";
}else{
node.style[attr] = iCur + speed + 'px';
}
}
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div></div>
</body>
</html>
案例
<!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>
/*
KFC 点餐系统
*/
function KFC(food, eatFunc){
//点餐的时候告诉他需要打包还是堂食,但不论使打包还是堂食都是出餐之后才进行
alert("您的餐" + food + "准备好了,请您及时就餐");
eatFunc(); //先声明,再执行此函数
}
// function xiaohua(){
// alert("打包带走");
// }
// KFC("老北京鸡肉卷",xiaohua);
// function xiaoming(){
// alert("堂食");
// }
/* var xiaoming = function(){
alert("堂食");
} */
KFC("香辣鸡腿堡", function(){ //函数在此执行
alert("堂食");
});
</script>
</head>
<body>
</body>
</html>
碰撞
<!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>
#div1{width: 100px; height: 100px; background-color: red; position: absolute; left: 100px; top: 200px;}
#div2{width: 100px; height: 100px; background-color: blue; position: absolute; left: 200px;}
</style>
<script>
window.onload = function(){
var oDiv1 = document.getElementById("div1");
var oDiv2 = document.getElementById("div2");
/*
让蓝色的块可以在当前页面上被拖拽
*/
oDiv2 .onmousedown = function(ev){
var e = ev || window.event;
var offsetX = e.clientX - oDiv2.offsetLeft;
var offsetY = e.clientY - oDiv2.offsetTop;
document.onmousemove = function(ev){
var e = ev || window.event;
//判断
if(konck(oDiv1, oDiv2)){
oDiv1.style.backgroundColor = 'black';
}else{
oDiv1.style.backgroundColor = 'red';
}
oDiv2.style.left = e.clientX - offsetX + 'px';
oDiv2.style.top = e.clientY - offsetY + 'px';
}
}
document.onmouseup = function(){
document.onmousemove = null;
}
}
/*
找两个物体怎样才会碰撞
思路:找两个物体绝对碰不到
*/
function konck(node1, node2){
var l1 = node1.offsetLeft;
var r1 = node1.offsetLeft + node1.offsetWidth;
var t1 = node1.offsetTop;
var b1 = node1.offsetTop + node1.offsetHeight;
var l2 = node2.offsetLeft;
var r2 = node2.offsetLeft + node2.offsetWidth;
var t2 = node2.offsetTop;
var b2 = node2.offsetTop + node2.offsetHeight;
if(l2 > r1 || r2 < l1 || t2 > b1 || b2 < t1){
return false;
}else{
return true;
}
}
</script>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
</body>
</html>
打砖块
<!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>
#div1{width: 600px; height: 600px; border: 1px solid black; position: relative; margin: 100px auto;}
#ball{width: 20px; height: 20px; background-color: cornflowerblue; border-radius: 50%; position: absolute; bottom: 30px; left: 290px;}
#bat{width: 100px; height: 30px; background-color: rgb(70, 70, 105); position: absolute; border: 1px solid black; bottom: 0px; left: 250px;}
#brick div{width: 98px; height: 18px; border: 1px solid black; float: left;}
</style>
<script>
window.onload = function(){
var oDiv = document.getElementById("div1");
var oBall = document.getElementById("ball");
var oBat = document.getElementById("bat");
var oBrick = document.getElementById("brick");
var oBricks = oBrick.getElementsByTagName("div");
dragX(oBat);
creatBrick(60);
//让小球可以水平方向运动,随机一个水平方向的速度
var speedX = parseInt(Math.random() * 4) + 3;
//让小球可以垂直方向运动,随机一个垂直方向的速度
var speedY = -(parseInt(Math.random() * 3) + 5);
setInterval(function(){
oBall.style.left = oBall.offsetLeft + speedX +'px';
oBall.style.top = oBall.offsetTop + speedY +'px';
if(oBall.offsetLeft >=580 || oBall.offsetLeft <= 0 ){
speedX *= -1;
}
if(oBall.offsetTop <= 0){
speedY *= -1;
}
if(oBall.offsetTop >= 580){
alert("GAME OVER");
window.location.reload();
}
/* 进行碰撞检测 */
//1、小球和拍子的碰撞检测
if(konck(oBall, oBat)){
speedY *= -1;
}
//2、小球和砖块发生碰撞
for(var i = 0; i < oBricks.length; i++){
if(konck(oBricks[i], oBall)){
speedY *= -1;
//砖块要被销毁
oBrick.removeChild(oBricks[i]);
break;
}
}
},30);
}
function dragX(node){
node.onmousedown = function(ev){
var e = ev || window.event;
var offsetX = e.clientX - node.offsetLeft;
document.onmousemove = function(ev){
var e = ev || window.event;
var l = e.clientX - offsetX;
//限制出界
if(l <= 0){
l = 0;
}
if(l >= 500){
l = 500;
}
node.style.left = l + 'px';
}
}
document.onmouseup = function(){
document.onmousemove = null;
}
}
//创建砖块 n:创建n个砖块
/*
文档流的转换:
让相对定位 转 绝对定位
*/
function creatBrick(n){
var oBrick = document.getElementById("brick");
for(var i = 0; i < n; i++){
var node = document.createElement("div");
node.style.backgroundColor = randomColor();
oBrick.appendChild(node);
}
var oBricks = oBrick.getElementsByTagName("div");
for(var i = 0; i < oBricks.length; i++){
oBricks[i].style.left = oBricks[i].offsetLeft + 'px';
oBricks[i].style.top = oBricks[i].offsetTop + 'px';
}
for(var i = 0; i < oBricks.length; i++){
oBricks[i].style.position = 'absolute';
}
}
function randomColor(){
var str = "rgba(" + parseInt(Math.random() * 256) + "," + parseInt(Math.random() * 256) + "," + parseInt(Math.random() * 256) + "," + parseInt(Math.random() * 256) + ")";
return str;
}
/*
找两个物体怎样才会碰撞
思路:找两个物体绝对碰不到
*/
function konck(node1, node2){
var l1 = node1.offsetLeft;
var r1 = node1.offsetLeft + node1.offsetWidth;
var t1 = node1.offsetTop;
var b1 = node1.offsetTop + node1.offsetHeight;
var l2 = node2.offsetLeft;
var r2 = node2.offsetLeft + node2.offsetWidth;
var t2 = node2.offsetTop;
var b2 = node2.offsetTop + node2.offsetHeight;
if(l2 > r1 || r2 < l1 || t2 > b1 || b2 < t1){
return false;
}else{
return true;
}
}
</script>
</head>
<body>
<div id="div1">
<div id="ball"></div>
<div id="bat"></div>
<div id="brick">
<!-- <div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div> -->
</div>
</div>
</body>
</html>
圆周运行
画圆的步骤:(同圆规画圆一致)
1、确定圆心
2、确定半径
3、旋转 (顺时针)
<!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>
#div1{position: absolute; width: 30px; height: 30px; background-color: red;}
</style>
<script>
/*
1弧度 = Math.PI / 180;
*/
window.onload = function(){
var oDiv = document.getElementById("div1");
//圆心的位置
var X = 400;
var Y = 400;
var r = 200;
var i = 0; //代表转过的弧度
setInterval(function(){
i++;
var radian = i * Math.PI / 180;
var a = Math.sin(radian) * r;
var b = Math.cos(radian) * r;
//计算圆上的点的具体位置
oDiv.style.left = X + a + 'px';
oDiv.style.top = Y - b + 'px';
//只设置以上的步骤是没有圆周运动的轨迹,可以利用结点的创建
var node = document.createElement("div");
node.style.width = '5px';
node.style.height = '5px';
node.style.backgroundColor = 'black';
node.style.position = 'absolute';
node.style.left = oDiv.offsetLeft + 'px';
node.style.top = oDiv.offsetTop + 'px';
document.body.appendChild(node);
}, 30);
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
完美运动框架
设置样式
<!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>
#div1{width: 100px; height: 100px; background-color: red;}
</style>
<script>
window.onload = function(){
var oDiv1 = document.getElementById("div1");
oDiv1.onclick = function(){
setStyle(this, 'width', '300px');
setStyle(this, 'height', '300px');
setStyle(this, 'backgroundColor', 'blue');
}
}
//设置css样式 必须使用这个方法进行修改
function setStyle(node, attr, value){
node.style[attr] = value;
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
设置样式(多个)
<!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>
#div1{width: 100px; height: 100px; background-color: red;}
</style>
<script>
window.onload = function(){
var oDiv1 = document.getElementById("div1");
oDiv1.onclick = function(){
setStyle(this, 'width', '300px');
setStyle(this, 'height', '300px');
setStyle(this, 'backgroundColor', 'blue');
}
}
//设置css样式 必须使用这个方法进行修改
function setStyle(node, attr, value){
node.style[attr] = value;
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
完美运动框架
<!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>
#div1{width: 100px; height: 100px; background-color: red; opacity: 1; filter: alpha(opacity=100);}
</style>
<script>
window.onload = function(){
var oDiv1 = document.getElementById("div1");
/*
宽高透明度同时发生变化
*/
oDiv1.onmouseover = function(){
// /*
// 这两个函数无法同时执行,因为每一个运动只有一个定时器,多次调用只能有一个运动生效
// */
// startMove(this, 'width', 300);
// startMove(this, 'height', 300);
startMove(this,{
width: 300,
height: 300,
opacity: 30
});
}
oDiv1.onmouseout = function(){
startMove(this,{
width: 100,
height: 100,
opacity: 100
});
}
}
function startMove(node, cssObj, complete){
clearInterval(node.timer);
node.timer = setInterval(function(){
for(var attr in cssObj){
/* 每隔30ms将所有的css样式都改变一次 */
var iTarget = cssObj[attr];
//计算速度
var iCur = null;
if(attr == 'opacity'){
iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
}else{
iCur = parseInt(getStyle(node,attr));
}
var speed = (iTarget - iCur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(iCur == iTarget){
clearInterval(node.timer);
if(complete){
complete.call(node);
}
}else{
if(attr == "opacity"){
iCur += speed;
node.style.opacity = iCur / 100;
node.style.filter = "alpha(opacity" + iCur + ")";
}else{
node.style[attr] = iCur + speed + 'px';
}
}
}
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
问题:
当宽高变化不为等比例的时候,先达到目的值的那个会关闭定时器
解决:当所有的动画到达目的值,才能关闭定时器
<!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>
#div1{width: 100px; height: 100px; background-color: red; opacity: 1; filter: alpha(opacity=100);}
</style>
<script>
window.onload = function(){
var oDiv1 = document.getElementById("div1");
startMove(this,{
width: 300,
height: 102,
opacity: 30
});
}
oDiv1.onmouseout = function(){
startMove(this,{
width: 100,
height: 100,
opacity: 100
});
}
}
function startMove(node, cssObj, complete){
clearInterval(node.timer);
node.timer = setInterval(function(){
var isEnd = true; //假设所有的动画都到达目的值
for(var attr in cssObj){
/* 每隔30ms将所有的css样式都改变一次 */
var iTarget = cssObj[attr];
//计算速度
var iCur = null;
if(attr == 'opacity'){
iCur = parseInt(parseFloat(getStyle(node, 'opacity')) * 100);
}else{
iCur = parseInt(getStyle(node,attr));
}
var speed = (iTarget - iCur) / 8;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(attr == "opacity"){
iCur += speed;
node.style.opacity = iCur / 100;
node.style.filter = "alpha(opacity" + iCur + ")";
}else{
node.style[attr] = iCur + speed + 'px';
}
if(iCur != iTarget){
isEnd = false;
}
}
if(isEnd){
clearInterval(node.timer);
if(complete){
complete.call(node);
}
}
},30);
}
//获取当前有效样式浏览器兼容的写法
function getStyle(node,cssStr){
return node.currentStyle ? node.currentStyle[cssStr] : getComputedStyle(node)[cssStr];
}
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>