- 勻速運動
- 加速運動
- 緩衝運動
- 碰撞運動
- 重力運動
- 多物體多值多鏈式運動框架
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>