js运动
1.匀速运动
<style type="text/css">
div {
width: 100px;
height: 100px;
background: orange;
position: absolute;
left: 0px;
top: 0px;
}
button {
margin-top: 150px;
}
span {
position: absolute;
left: 300px;
top: 0px;
width: 1px;
height: 100px;
background: black;
}
</style>
</head>
<body>
<div></div>
<span></span>
<button id="btn">run</button>
<script>
var oDiv = document.getElementsByTagName('div')[0];
var oBtn = document.getElementById('btn');
var timer = null;
oBtn.onclick = function () {
// s = vt t s
startMove(oDiv , 300);//让谁运动,运动到哪里
}
function startMove (dom, target) {
clearInterval(timer);
var iSpeed = target - dom.offsetLeft> 0 ? 7 : -7;
timer = setInterval(function () {
if (Math.abs(target-dom.offsetLeft) < Math.abs(iSpeed)) {
clearInterval(timer);
dom.style.left = target+'px';
}else {
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}
}, 30);
}
</script>
2.缓冲运动
<style type="text/css">
div {
width: 100px;
height: 100px;
background: orange;
position: absolute;
left: 0px;
top: 0px;
}
button {
margin-top: 150px;
}
span {
position: absolute;
left: 300px;
top: 0px;
width: 1px;
height: 100px;
background: black;
}
</style>
</head>
<body>
<div></div>
<span></span>
<button id="btn">run</button>
<script>
var oDiv = document.getElementsByTagName('div')[0];
var oBtn = document.getElementById('btn');
var timer = null;
oBtn.onclick = function () {
// s = vt t s
startMove(oDiv , 300);//让谁运动,运动到哪里
}
// 物体的速度 距离目标点越近 就越小 当到达目标点时 速度减小为0
function startMove (dom, target) {
clearInterval(timer);
var iSpeed = null;
timer = setInterval(function () {
iSpeed = (target - oDiv.offsetLeft) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);//像素原因
if(oDiv.offsetLeft == target){
clearInterval(timer);
}else {
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}
}, 30);
}
</script>
类似电脑清楚缓存球的动态
<style type="text/css">
.wrapper {
width: 400px;
height: 80px;
background: orange;
position: absolute;
left: -400px;
top: 200px;
}
.wrapper span {
width: 50px;
height: 80px;
background: red;
position: absolute;
right: -50px;
top: 0px;
}
</style>
</head>
<body>
<div class="wrapper">
<span></span>
</div>
<script>
var oDiv = document.getElementsByClassName('wrapper')[0];
timer=null;
oDiv.onmouseenter = function () {
startMove(this, 0);
}
oDiv.onmouseleave = function () {
startMove(this, -400);
}
function startMove (dom, target) {
clearInterval(timer);
var iSpeed = null;
timer = setInterval(function () {
iSpeed = (target - oDiv.offsetLeft) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);//像素原因
if(oDiv.offsetLeft == target){
clearInterval(timer);
}else {
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}
}, 30);
}
</script>
透明度渐变缓存
<style type="text/css">
div {
width: 100px;
height: 100px;
background: red;
opacity: 1;
}
</style>
</head>
<body>
<div>
</div>
<script>
var timer = null;
var oDiv=document.getElementsByTagName('div')[0];
//获取样式精准的值
oDiv.onclick=function (){
startMove(this , 0.5);
}
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, target) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
iCur = parseFloat( getStyle(dom, 'opacity') ) * 100;
iSpeed = ( target - iCur ) / 7;
// ....
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(dom.timer);
}else {
dom.style.opacity = (iCur + iSpeed)/100;
}
}, 30);
}
</script>
3.多物体运动
<style type="text/css">
div {
width: 100px;
height: 100px;
background: red;
margin-bottom: 100px;
}
</style>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<script>
var timer = null;
var oDivArray = document.getElementsByTagName('div');
for (var i = 0; i < oDivArray.length; i++) {
oDivArray[i].onmouseenter = function () {
startMove(this, 400);
}
oDivArray[i].onmouseleave = function () {
startMove(this, 100);
}
}
//获取样式精准的值
// oDiv.οnclick=function (){
// startMove(this , 0.5);
// }
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, target) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
iCur = parseFloat( getStyle(dom, 'width') ) ;
iSpeed = ( target - iCur ) / 7;
// ....
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(dom.timer);
}else {
dom.style.width = iCur + iSpeed + 'px';
}
}, 30);
}
</script>
物体不同运动
<style type="text/css">
div {
width: 100px;
height: 100px;
background: red;
margin-bottom: 100px;
border: 5px solid black;
}
</style>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<script>
var timer = null;
var oDivArray = document.getElementsByTagName('div');
oDivArray[0].onclick = function () {
startMove(this, 'width', 400);
}
oDivArray[1].onclick = function () {
startMove(this, 'height', 400);
}
oDivArray[2].onclick = function () {
startMove(this, 'borderWidth', 20);
}
oDivArray[3].onclick = function () {
startMove(this, 'opacity', 50);
}
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, attr, target) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
if (attr == 'opacity') {
iCur = parseFloat( getStyle(dom, attr) ) * 100;
}else {
iCur = parseInt( getStyle(dom, attr) );
}
iSpeed = (target - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(dom.timer);
}
if (attr == 'opacity') {
dom.style.opacity = ( iCur + iSpeed ) / 100;
}else {
dom.style[attr] = iCur + iSpeed + 'px';
}
}, 30)
}
</script>
多物体不同值运动
<style type="text/css">
div {
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background: red;
opacity: 1;
}
#topDiv {
top: 200px;
}
#bottomDiv {
top: 400px;
}
</style>
</head>
<body>
<div id="topDiv"></div>
<div id="bottomDiv"></div>
<script>
var timer = null;
// width -> 100 400 height 100 400 left 0 200 top 200 300 opacity 1 0.5
// {width: 400, height: 400, left: 200, top: 300, opacity: 50}
var oTopDiv = document.getElementById('topDiv');
var oBottomDiv = document.getElementById('bottomDiv');
oTopDiv.onclick = function () {
// 当一次性传多值时,且不知道传几个,用对象
startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
})
}
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, attrObj) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
var bStop = true;
//通过循环来改变是属性
for (var attr in attrObj) {
// 'width' 'height'
if (attr == 'opacity') {
iCur = parseFloat( getStyle(dom, attr) ) * 100;
}else {
iCur = parseInt( getStyle(dom, attr) );
}
iSpeed = (attrObj[attr] - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (attr == 'opacity') {
dom.style.opacity = (iCur + iSpeed) / 100;
}else {
dom.style[attr] = iCur + iSpeed + 'px';
}
if (iCur != attrObj[attr]) {
bStop = false;
}
}
if (bStop) {
clearInterval(dom.timer);
alert("over");
}
}, 30);
}
</script>
多物体多值运动+回调机制
<style type="text/css">
div {
position: absolute;
left: 0px;
width: 100px;
height: 100px;
background: red;
opacity: 1;
}
#topDiv {
top: 200px;
}
#bottomDiv {
top: 400px;
}
</style>
</head>
<body>
<div id="topDiv"></div>
<div id="bottomDiv"></div>
<script>
var timer = null;
// width -> 100 400 height 100 400 left 0 200 top 200 300 opacity 1 0.5
// {width: 400, height: 400, left: 200, top: 300, opacity: 50}
var oTopDiv = document.getElementById('topDiv');
var oBottomDiv = document.getElementById('bottomDiv');
oTopDiv.onclick = function () {
// 当一次性传多值时,且不知道传几个,用对象
startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
startMove(oBottomDiv, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
alert('over');
})
})
}
function getStyle (dom, attr) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[attr];
}else {
return dom.currentStyle[attr];
}
}
function startMove (dom, attrObj, callback) {
clearInterval(dom.timer);
var iSpeed = null, iCur = null;
dom.timer = setInterval(function () {
var bStop = true;
//通过循环来改变是属性
for (var attr in attrObj) {
// 'width' 'height'
if (attr == 'opacity') {
iCur = parseFloat( getStyle(dom, attr) ) * 100;
}else {
iCur = parseInt( getStyle(dom, attr) );
}
iSpeed = (attrObj[attr] - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (attr == 'opacity') {
dom.style.opacity = (iCur + iSpeed) / 100;
}else {
dom.style[attr] = iCur + iSpeed + 'px';
}
if (iCur != attrObj[attr]) {
bStop = false;
}
}
if (bStop) {
clearInterval(dom.timer);
typeof callback == 'function' && callback();
}
}, 30);
}
</script>
加速度运动
<style type="text/css">
div {
position: absolute;
left: 0px;
top: 0px;
width: 100px;
height: 100px;
background: orange;
}
</style>
</head>
<body>
<div ></div>
<script>
var timer = null;
// v = v + at;
var oDiv = document.getElementsByTagName('div')[0];
var timer = null;
oDiv.onclick = function () {
startMove(this);
}
// 加速度不变的加速运动 运动方向是向右
// 加速度不变的减速运动 加速不变的加速运动 向左
function startMove (dom) {
clearInterval(timer);
var a = 2;
var iSpeed = 20;
timer = setInterval(function () {
iSpeed = iSpeed + a;
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}, 30);
};
</script>
弹性运动
<style type="text/css">
div {
position: absolute;
left: 0px;
top: 0px;
width: 100px;
height: 100px;
background: orange;
}
span {
position: absolute;
left: 300px;
top: 0px;
background: black;
width: 2px;
height: 100px;
}
</style>
</head>
<body>
<div></div>
<span></span>
<script>
var oDiv = document.getElementsByTagName('div')[0];
var timer = null;
oDiv.onclick = function (){
startMove(this , 300);
}
function startMove ( dom , target){
clearInterval(timer);
var a =3;
var ispeed = 0 ;
//实际损耗 mv
var u = 0.5 ;
timer = setInterval(function(){
a = (target - dom.offsetLeft) / 10 ;
ispeed += a;
//默认摩擦力
ispeed *=0.8;
//在浏览器中运动的物体没有真正的停止,所以近似把绝对值为小于1 看成速度为0
if ( Math.abs(ispeed) < 1 && Math.abs(target -dom.offsetLeft) <1){
clearInterval(timer);
dom.style.left = target + 'px';
}else{
dom.style.left = dom.offsetLeft + ispeed +'px';
}
dom.style.left = dom.offsetLeft + ispeed + 'px' ;
},30)
}
</script>
弹性运动案例
<style>
* {
padding: 0px;
margin: 0px;
list-style: none;
}
ul {
position: relative;
margin: 100px auto;
width: 800px;
height: 100px;
}
.ele {
float: left;
width: 198px;
border: 1px solid black;
height: 98px;
line-height: 98px;
text-align: center;
background: aqua;
}
.bg {
position: absolute;
left: 0px;
top: 0px;
width: 200px;
height: 100px;
opacity: 0.5;
background: deeppink;
}
</style>
</head>
<body>
<ul>
<li class="ele">CS</li>
<li class="ele">CG</li>
<li class="ele">LD</li>
<li class="ele">DCG</li>
<li class="bg"></li>
</ul>
<script>
var oLiArray = document.getElementsByTagName('li');
var oBg = oLiArray[oLiArray.length - 1];
var timer = null;
for (var i =0; i < oLiArray.length - 1; i++) {
oLiArray[i].onmouseenter = function () {
console.log(this.offsetLeft);
startMove(oBg, this.offsetLeft);
}
}
function startMove (dom, target) {
clearInterval(timer);
var iSpeed = 0;
var a = 1;
var u = 0.8;
timer = setInterval(function () {
a = (target - dom.offsetLeft) / 5;
iSpeed += a;
iSpeed *= u;
console.log(iSpeed, target - dom.offsetLeft);
if ( Math.abs(iSpeed) < 1 && Math.abs(target - dom.offsetLeft) < 1) {
clearInterval(timer);
dom.style.left = target + 'px';
}else {
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}
}, 30);
}
</script>
模拟重力场
多方向运动+碰撞检测+重力加速度+能量损失
问题1:碰撞边界后反弹的处理
解决:首先要判定边界,在小球向下运动的反弹条件是小球的下边线碰到窗口的下边线,由于存在小球的下边线没有刚好处在窗口下边线的情况,则反弹的判定条件是,让小球的offsetTop(小球上边线与窗口的上边线的距离)大于等于窗口可视区的高度减去小球的直径(高度),此时为了防止反弹点不在窗口底边线,则设置小球的offsetTop等于窗口可视区的高度减去小球的直径。反弹后垂直方向上的速度方向改变,可设置speed = -speed;小球在向上运动时反弹的点在上边线上,此时的处理与下边线类似;左右碰撞原理与上下碰撞原理类似,不做赘述。
问题2:碰撞后的动能损耗
解决:动能损耗直观上来讲,就是速度降低,这里拟损耗后的速度为损耗前的0.8倍
问题3:清理定时器的条件
解决:现实中小球停止时,水平和垂直方向的速度均为零,且落在地面上。而模拟的过程发现小球的速度不能为零,但是数值太小不足以引起位置变化,故当水平和垂直方向上的速度均小于1,且小球下边线在窗口下边线(小球的offsetTop等于窗口可视区的高度减去小球的直径)时,设置速度为零并清理定时器。
<style>
div {
width: 100px;
height: 100px;
background: orange;
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div id="demo"></div>
<script>
var oDiv = document.getElementById('demo');
oDiv.onclick = function () {
startMove(this);
}
function startMove (dom) {
clearInterval(dom.timer);
var iSpeedX = 6;
var iSpeedY = 8;
var g = 3;//重力加速度
dom.timer = setInterval(function () {
iSpeedY += g;
var newTop = dom.offsetTop + iSpeedY;
var newLeft = dom.offsetLeft + iSpeedX;
if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {
iSpeedY *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newTop = document.documentElement.clientHeight - dom.clientHeight;
}
if (newTop <= 0) {
iSpeedY *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newTop = 0;
}
if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {
iSpeedX *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newLeft = document.documentElement.clientWidth - dom.clientWidth;
}
if (newLeft <= 0) {
iSpeedX *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newLeft = 0;
}
//做停止的判断
if (Math.abs(iSpeedX) < 1) {
iSpeedX = 0;
}
if (Math.abs(iSpeedY) < 1) {
iSpeedY = 0;
}
if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom.clientHeight) {
clearInterval(dom.timer);
console.log('over')
}else {
dom.style.top = newTop + 'px';
dom.style.left = newLeft + 'px';
}
}, 30);
}
</script>
拖拽实例
<style>
div {
width: 100px;
height: 100px;
background: orange;
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div id="demo"></div>
<script>
var oDiv = document.getElementById('demo');
var lastX = 0;
var lastY = 0;
var iSpeedX = 0;
var iSpeedY = 0;
oDiv.onmousedown = function (e) {
clearInterval(this.timer);
var event = event || e;
//鼠标距离左侧的位置 鼠标指针相对于浏览器页面(或客户区)的水平坐标。 距离边界的位置
var disX = event.clientX - this.offsetLeft;
var disY = event.clientY - this.offsetTop;
var self = this;
document.onmousemove = function (e) {
var event = event || e;
var newLeft = event.clientX - disX;
var newTop = event.clientY - disY;
//计算松手时的速度
iSpeedX = newLeft - lastX;
iSpeedY = newTop - lastY;
//更新最后松手前的位置
lastX = newLeft;
lastY = newTop;
// //拖拽时留下的痕迹
// var oSpan = document.createElement('span');
// oSpan.style.position = 'absolute';
// oSpan.style.left = newLeft + 'px';
// oSpan.style.top = newTop + 'px';
// oSpan.style.width = '5px';
// oSpan.style.height = '5px';
// oSpan.style.backgroundColor = 'black';
// document.body.appendChild(oSpan);
self.style.left = newLeft + 'px';
self.style.top = newTop + 'px';
}
document.onmouseup = function () {
document.onmouseup = null;
document.onmousemove = null;
startMove(self, iSpeedX, iSpeedY);
}
}
function startMove(dom, iSpeedX, iSpeedY) {
clearInterval(dom.timer);
var g = 3; //重力加速度
dom.timer = setInterval(function () {
iSpeedY += g;
var newTop = dom.offsetTop + iSpeedY;
var newLeft = dom.offsetLeft + iSpeedX;
if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {
iSpeedY *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newTop = document.documentElement.clientHeight - dom.clientHeight;
}
if (newTop <= 0) {
iSpeedY *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newTop = 0;
}
if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {
iSpeedX *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newLeft = document.documentElement.clientWidth - dom.clientWidth;
}
if (newLeft <= 0) {
iSpeedX *= -1;
//能量损失
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newLeft = 0;
}
//做停止的判断
if (Math.abs(iSpeedX) < 1) {
iSpeedX = 0;
}
if (Math.abs(iSpeedY) < 1) {
iSpeedY = 0;
}
if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom
.clientHeight) {
clearInterval(dom.timer);
console.log('over')
} else {
dom.style.top = newTop + 'px';
dom.style.left = newLeft + 'px';
}
}, 30);
}
</script>