- 匀速运动
- 加速运动
- 缓冲运动
- 碰撞运动
- 重力运动
- 多物体多值多链式运动框架
1. 匀速运动
速度isSpeed是个定值
function startmov(obj) {
clearInterval(timer);
var isSpeed = 10;
timer = setInterval(function () {
obj.style.left = obj.offsetLeft + isSpeed + 'px';
},30);
}
2. 变速运动
核心就是isSpeed每次执行发生改变
// 变速运动
function starSpeedChangeMove(obj,target) {
clearInterval(timer);
var isSpeed;
timer = setInterval(function () {
isSpeed = (target - obj.offsetLeft) / 15;
isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
obj.style.left = obj.offsetLeft + isSpeed + 'px';
},30);
}
应用(伸缩栏)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.wrapper{
position : absolute;
top: 200px;
left: -400px;
width: 400px;
height: 100px;
background: yellowgreen;
}
.demo{
position: absolute;
top: 0;
left: 400px;
width: 40px;
height: 100px;
background: yellow;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="demo">
</div>
</div>
<script>
var oDivDemo = document.getElementsByClassName('wrapper')[0];
var timer = null;
oDivDemo.onmouseenter = function () {
starSpeedChangeMove(this,0);
}
oDivDemo.onmouseleave = function () {
starSpeedChangeMove(this,-400);
}
function starSpeedChangeMove(obj,target) {
clearInterval(timer);
var isSpeed;
timer = setInterval(function () {
isSpeed = (target - obj.offsetLeft) / 15;
isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
obj.style.left = obj.offsetLeft + isSpeed + 'px';
},30);
}
</script>
</body>
</html>
3. 缓冲运动
顾名思义,所谓缓冲,就是说速度不同;在一定条件下,距离越大,速度越大;距离越小,速度也就越小。
也就是跟变速运动差不多代码
4.碰撞运动(弹性运动)
在发生碰撞的时候,我们把对应的x,y方向的速度乘以"摩擦系数"
// 弹性运动
function starMove (obj, target) {
clearInterval(obj.timer);
var isSpeed = 20;
var a, u = 0.8; // u表示摩擦系数
obj.timer = setInterval(function (){
a = (target - obj.offsetLeft) / 15;
isSpeed = isSpeed + a;
isSpeed = isSpeed * 0.9;
if(Math.abs(isSpeed) < 1 && Math.abs(target - obj.offsetLeft) < 1){
clearInterval(obj.timer);
}else{
obj.style.left = obj.offsetLeft + isSpeed + 'px';
}
},30);
}
应用(弹性导航栏)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
*{
margin: 0px;
padding: 0px;
list-style: none;
}
ul{
position: relative;
width: 600px;
height: 80px;
/* border: 1px solid #000; */
margin : 100px auto 0;
}
ul li.nav{
width: 148px;
height: 78px;
border: 1px solid #000;
color : #000;
text-align: center;
line-height: 78px;
float: left;
}
ul li.bg{
position: absolute;
top: 0px;
left: 0px;
width: 150px;
height: 80px;
background: rgb(214, 49, 49);
z-index: -1;
}
</style>
</head>
<body>
<ul>
<li class="nav">ES6</li>
<li class="nav">Webpack</li>
<li class="nav">Vue</li>
<li class="nav">Node</li>
<li class="bg"></li>
</ul>
<script>
var oLi = document.getElementsByTagName('li');
var oBg = document.getElementsByClassName('bg')[0];
var oLiArr = Array.prototype.slice.call(oLi, 0);
oLiArr.forEach(function (ele, index){
ele.onmouseenter = function (){
starMove(oBg,this.offsetLeft);
}
});
function starMove (obj, target) {
clearInterval(obj.timer);
var isSpeed = 20;
var a, u = 0.8; // u表示摩擦系数
obj.timer = setInterval(function (){
a = (target - obj.offsetLeft) / 15;
isSpeed = isSpeed + a;
isSpeed = isSpeed * 0.9;
if(Math.abs(isSpeed) < 1 && Math.abs(target - obj.offsetLeft) < 1){
clearInterval(obj.timer);
}else{
obj.style.left = obj.offsetLeft + isSpeed + 'px';
}
},30);
}
</script>
</body>
</html>
5. 重力运动
// targetSpeedX,targetSpeedY 表示的是x,y速度矢量值
function starMove (obj,targetSpeedX,targetSpeedY){
clearInterval(obj.timer);
var iSpeedX,
iSpeedY,
g = 10, // 重力加速度
u = 0.8; // 碰撞时速度损失
iSpeedX = (typeof targetSpeedX == 'undefined' ? 6 : targetSpeedX),
iSpeedY = (typeof targetSpeedY == 'undefined' ? 8 : targetSpeedY);
console.log(iSpeedY,iSpeedX);
obj.timer = setInterval(function (){
iSpeedY += g;
var newLeft = obj.offsetLeft + iSpeedX,
newTop = obj.offsetTop + iSpeedY;
// 边界处理
if(newTop >= document.documentElement.clientHeight - obj.offsetHeight){
iSpeedY *= -1;
iSpeedY *= u;
iSpeedX *= u;
newTop = document.documentElement.clientHeight - obj.offsetHeight;
}
if(newTop <= 0){
iSpeedY *= -1;
iSpeedY *= u;
iSpeedX *= u;
newTop = 0;
}
if(newLeft >= document.documentElement.clientWidth - obj.offsetWidth){
iSpeedX *= -1;
iSpeedX *= u;
newLeft = document.documentElement.clientWidth - obj.offsetWidth;
}
if(newLeft <= 0){
iSpeedX *= -1;
iSpeedX *= u;
newLeft = 0;
}
// 判断结束条件
if(Math.abs(document.documentElement.clientHeight-obj.offsetHeight-newTop) < 1 && Math.abs(iSpeedY) < 1){
clearInterval(obj.timer);
}else{
obj.style.left = newLeft + 'px';
obj.style.top = newTop + 'px';
}
},30);
}
应用(拖拽抛出效果)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body{
overflow: hidden;
}
.demo{
position: absolute;
left: 0px;
top: 0px;
width: 100px;
height: 100px;
border-radius: 50%;
background: #000;
}
</style>
</head>
<body>
<div class="demo"></div>
<script>
var oDiv = document.getElementsByClassName('demo')[0];
// oDiv.onclick = function (){
// starMove(this,1,1);
// }
var lastX = oDiv.offsetLeft,
lastY = oDiv.offsetTop;
oDiv.onmousedown = function (e) {
var event = e || window.event;
var disX = event.clientX - this.offsetLeft,
disY = event.clientY - this.offsetTop,
that = this;
var iSpeedX = 0,
iSpeedY = 0;
document.onmousemove = function (e) {
var newLeft = e.clientX - disX,
newTop = e.clientY - disY;
iSpeedX = newLeft - lastX,
iSpeedY = newTop - lastY,
lastX = newLeft,
lastY = newTop;
that.style.left = newLeft + 'px';
that.style.top = newTop + 'px';
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
//iSpeedX,iSpeedY 相当于是速度的方向差值 正负表示方向
starMove(that,iSpeedX,iSpeedY);
}
}
}
// 模拟重力场
// targetSpeedX,targetSpeedY 表示的是x,y速度矢量值
function starMove (obj,targetSpeedX,targetSpeedY){
clearInterval(obj.timer);
var iSpeedX,
iSpeedY,
g = 10, // 重力加速度
u = 0.8; // 碰撞时速度损失
iSpeedX = (typeof targetSpeedX == 'undefined' ? 6 : targetSpeedX),
iSpeedY = (typeof targetSpeedY == 'undefined' ? 8 : targetSpeedY);
console.log(iSpeedY,iSpeedX);
obj.timer = setInterval(function (){
iSpeedY += g;
var newLeft = obj.offsetLeft + iSpeedX,
newTop = obj.offsetTop + iSpeedY;
// 边界处理
if(newTop >= document.documentElement.clientHeight - obj.offsetHeight){
iSpeedY *= -1;
iSpeedY *= u;
iSpeedX *= u;
newTop = document.documentElement.clientHeight - obj.offsetHeight;
}
if(newTop <= 0){
iSpeedY *= -1;
iSpeedY *= u;
iSpeedX *= u;
newTop = 0;
}
if(newLeft >= document.documentElement.clientWidth - obj.offsetWidth){
iSpeedX *= -1;
iSpeedX *= u;
newLeft = document.documentElement.clientWidth - obj.offsetWidth;
}
if(newLeft <= 0){
iSpeedX *= -1;
iSpeedX *= u;
newLeft = 0;
}
// 判断结束条件
if(Math.abs(document.documentElement.clientHeight-obj.offsetHeight-newTop) < 1 && Math.abs(iSpeedY) < 1){
clearInterval(obj.timer);
}else{
obj.style.left = newLeft + 'px';
obj.style.top = newTop + 'px';
}
},30);
}
</script>
</body>
</html>
6. 多物体多值多链式运动框架
多物体运动:
让每一个运动的物体拥有自己的定时器 定时器独立
把定时器作为对象的属性 让定时器独立
链式运动
上一个动作结束 进入到下一个动作
解决 : 在运动函数上加一个参数,参数代表回调函数
参数说明:obj 对应元素,
json 对象, 属性是改变的样式,比如 width height opacity
callback 回调函数 可以进行多个动作发生
小技巧: opacity 改变的时候,可以把isSpeed扩大100倍,最后在缩小100倍
function startMove(obj, json, callback){
clearInterval(obj.timer);
obj.timer = setInterval(function (){
var oBstop = true,
isSpeed,
iCur;
for(var attr in json){
if(attr == 'opacity'){
iCur = parseFloat(getStyle(obj,attr)) * 100;
}else{
iCur = parseInt(getStyle(obj,attr));
}
isSpeed = (json[attr] - iCur) / 7;
isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
if(attr == 'opacity'){
obj.style.opacity = (isSpeed + iCur) / 100;
}else{
obj.style[attr] = (isSpeed + iCur) + 'px';
}
if(json[attr] != iCur){
oBstop = false;
}
}
if(oBstop){
clearInterval(obj.timer);
typeof callback == 'function' ? callback() : "";
}
},30);
}
demo(具体用法)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div{
position : absolute;
left: 0;
width: 100px;
height: 100px;
background : red;
opacity: 1;
border : 1px solid #000;
margin: 100px;
}
.top {
top : 100px;
}
.buttom {
bottom : 100px;
}
</style>
</head>
<body>
<div class="top">1</div>
<div class="buttom">2</div>
<script>
var oDiv = document.getElementsByTagName('div');
var timer = null;
var targetObj = {
width : 400,
height : 400,
opacity : 20,
left : 200,
top : 200
}
oDiv[0].onclick = function (){
startMove(this,targetObj,function (){
console.log('this == ', this);
startMove(oDiv[1],targetObj);
});
console.log(222);
}
// 多物体多链式运动框架
function getStyle (obj, attr) {
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return window.getComputedStyle(obj,false)[attr];
}
}
function startMove(obj, json, callback){
clearInterval(obj.timer);
obj.timer = setInterval(function (){
var oBstop = true,
isSpeed,
iCur;
for(var attr in json){
if(attr == 'opacity'){
iCur = parseFloat(getStyle(obj,attr)) * 100;
}else{
iCur = parseInt(getStyle(obj,attr));
}
isSpeed = (json[attr] - iCur) / 7;
isSpeed = isSpeed > 0 ? Math.ceil(isSpeed) : Math.floor(isSpeed);
if(attr == 'opacity'){
obj.style.opacity = (isSpeed + iCur) / 100;
}else{
obj.style[attr] = (isSpeed + iCur) + 'px';
}
if(json[attr] != iCur){
oBstop = false;
}
}
if(oBstop){
clearInterval(obj.timer);
typeof callback == 'function' ? callback() : "";
}
},30);
}
</script>
</body>
</html>