运动课笔记2

"Hello World, Hello Blog"

Posted by wudimingwo on December 15, 2018

来源渡一笔记

匀加速运动

1
2
3
4
5
6
7
8
9
10
function move (dom,attr) {
            	var speed = 0;
            	var a = 3;
            	clearInterval(dom.timer);
            	dom.timer = setInterval(function () {
            		speed += a;
            		dom.style[attr] = parseInt(getStyle(dom,attr)) + speed + 'px';
            	},30);
move (div,'left')
getStyle 函数在运动课笔记1

弹性运动(匀加速)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function move (dom,attr,target) {
            	var speed = 0;
            	var a = 3;
            	clearInterval(dom.timer);
            	dom.timer = setInterval(function () {
            	  var iCur = parseInt(getStyle(dom,attr));
            	  if(target < iCur) {
            	    speed -= a;
            	  }else {
            	    speed += a;
            	  }
            		dom.style[attr] = iCur + speed + 'px';
            	},30);
            }

move(div,'left',300);

加速度为常量,跟target距离不成正比,非弹簧运动。

弹性运动(理想弹簧运动)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 function move (dom,attr,target) {
            	var speed = 0;
            	var a = 0;
            	clearInterval(dom.timer);
            	dom.timer = setInterval(function () {
            	  var iCur = parseInt(getStyle(dom,attr));
            	  a = (target - iCur) / 20;
            	  speed += a;
            		dom.style[attr] = iCur + speed + 'px';
            	},30);
            }
move(div,'left',100);


a = (target - iCur) / 20;
speed = (target - iCur) / 7;(缓冲运动中)
这两个很类似。表示的都是与距离成正比。

弹簧运动(模拟现实) 版本1.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function move (dom,attr,target) {
            	var speed = 0;
            	var a = 0;
            	var u = 0.8;
            	clearInterval(dom.timer);
            	dom.timer = setInterval(function () {
            	  var iCur = parseInt(getStyle(dom,attr));
            	  a = (target - iCur) / 20;
            	  speed += a;
            	  speed *= u;
            		dom.style[attr] = iCur + speed + 'px';
            		console.log(speed,target - iCur);
            		if(Math.abs(speed) < 1 && Math.abs(target - iCur) < 1){//此处为条件1
            		  clearInterval(dom.timer);
            		}
            		
            	},30);
            }

其实有很多细节我也不太理解。
比如条件1 在缓冲运动中,Math.abs(target-iCur) 有时会卡死在>1的时候。
可在这里似乎不存在>1卡死的情况。

结果发现这也是有可能会卡死的。
如果把上面的u 改成0.8 就会卡死,永远都无法执行 清除计时器操作。
如果我们放入一个回调函数,那么回调函数就不会执行了。

其实这就很尴尬。我们最好找到一个合适的条件,可以保证能够会被执行,
然后停止的足够自然。

版本1.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
首先想到的就是缓冲运动中的取整
function move (dom,attr,target) {
            	var speed = 0;
            	var a = 0;
            	var u = 0.8;
            	clearInterval(dom.timer);
            	dom.timer = setInterval(function () {
            	  var iCur = parseInt(getStyle(dom,attr));
            	  a = (target - iCur) / 20;
            	  speed += a;
            	  speed *= u;
            	  speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);//首先联想到这个
            		dom.style[attr] = iCur + speed + 'px';
            		console.log(speed,target - iCur);
            		if(Math.abs(speed) <= 1 && Math.abs(target - iCur) < 1){
            		  clearInterval(dom.timer);
            		}
            		
            	},30);
            }

不行,他会不停摇摆。

版本1.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function move (dom,attr,target) {
            	var speed = 0;
            	var a = 0;
            	var u = 0.8;
            	var last = 'a';
            	var count = {};
            	clearInterval(dom.timer);
            	dom.timer = setInterval(function () {
            	  var iCur = parseInt(getStyle(dom,attr));
            	  a = (target - iCur) / 20;
            	  speed += a;
            	  speed *= u;
            		dom.style[attr] = iCur + speed + 'px';
            		console.log(speed,target - iCur);
            		if(last == (target - iCur) && count[last] >=5 && Math.abs(speed) < 1){
            		  clearInterval(dom.timer);
            		  dom.style[attr] = target + 'px';
            		}else{
            		  last = target - iCur;
            		  if(!count[last]){
            		    count[last] = 1;
            		  }
            		  count[last]++;
            		}
            	},30);
            }
写得比较丑,
思路是,最后卡死时,位置必然是不动的,我们记录最后的位置一样的次数超过好几次,
并且speed < 0
那么基本就可以判定运动已经卡死,可以停止。

多值多属性链式运动 根据版本1.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function move (dom,option,callback) {
              var speed = 0;
              var a = 0;
              var u = 0.95;
              var target = {};
              clearInterval(dom.timer);
              dom.timer = setInterval(function () {
                var stop = true;
                for(var attr in option){
                  target[attr] = option[attr] * 100;
                  
                  var iCur = parseFloat(getStyle(dom,attr)) * 100;
                  a = (target[attr] - iCur) / 20;
                  speed += a;
                  speed *= u;
                  console.log(speed,target[attr] - iCur);
                  if(!(Math.abs(speed) < 1 && Math.abs(target[attr] - iCur) < 1)){
                    stop = false;
                    if(attr == 'opacity') {
                      dom.style[attr] = (iCur + speed)/100;
                    }else {
                      dom.style[attr] = iCur/100 + speed/100 + 'px';
                    }
                  }
                  if(stop) {
                    clearInterval(dom.timer);
                    console.log(111);
                    typeof(callback)=="function" ? callback():'';
                  }
                }
              },30);
            }
其实这都需要时不时的写一写,有好处。

模拟边界(匀速运动)(速度反方向问题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function move (div) {
            	var speedx = 10,
            	    speedy = 10;
            	clearInterval(div.timer);
            	div.timer = setInterval(function () {
            		var newLeft = parseInt(getStyle(div,'left')) + speedx; 
            		var newTop = parseInt(getStyle(div,'top')) + speedy; 
            		console.log(document.body.clientHeight);
            		if(newTop >= document.documentElement.clientHeight - div.offsetHeight){
            		  speedy *= -1;
            		  newTop = document.documentElement.clientHeight - div.offsetHeight;
            		}
            		if(newTop <= 0) {
            		  speedy *= -1;
            		  newTop = 0;
            		}
            		if(newLeft <= 0) {
            		  speedx *= -1;
            		  newLeft = 0;
            		}
            		if(newLeft >= document.body.clientWidth - div.offsetWidth){
            		  speedx *= -1;
            		  newLeft = document.body.clientWidth - div.offsetWidth;
            		}
            		
            		div.style['left'] = newLeft + 'px';
            		div.style['top'] = newTop + 'px';
            	},30);
            	
            }

模拟重力场(拖拽)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
function getStyle (dom,attr) {
            	if (dom.currentStyle) {
            		return dom.currentStyle[attr];
            	} else{
            		return window.getComputedStyle(dom,null)[attr];
            	}
            }
            
            function move (div,speedx,speedy) {
            	  var g = 8,
            	    u = 0.8;
            	clearInterval(div.timer);
            	div.timer = setInterval(function () {
            	  speedy += g;
            		var newLeft = parseInt(getStyle(div,'left')) + speedx; 
            		var newTop = parseInt(getStyle(div,'top')) + speedy; 
            		if(newTop >= document.documentElement.clientHeight - div.offsetHeight){
            		  speedy *= -1;
            		  speedx *= u;
            		  speedy *= u;
            		  console.log(speedy);
            		  newTop = document.documentElement.clientHeight - div.offsetHeight;
            		}
            		if(newTop <= 0) {
            		  speedy *= -1;
            		  speedx *= u;
            		  speedy *= u;
            		  newTop = 0;
            		}
            		if(newLeft <= 0) {
            		  speedx *= -1;
            		  speedx *= u;
            		  newLeft = 0;
            		}
            		if(newLeft >= document.body.clientWidth - div.offsetWidth){
            		  speedx *= -1;
            		  speedx *= u;
            		  newLeft = document.body.clientWidth - div.offsetWidth;
            		}
            		if(Math.abs(speedx) < g && Math.abs(speedy) < g && newTop == document.documentElement.clientHeight - div.offsetHeight) {// 这个停止条件实际上挺费神的
            		  clearInterval(div.timer);
            		  console.log(123456);
            		}
            		div.style['left'] = newLeft + 'px';
            		div.style['top'] = newTop + 'px';
            	},20);
            	
            }
            
            
            div.onmousedown = function (e) {
            	var e = e || window.event;
            	clearInterval(div.timer);
            	var disX = e.clientX - this.offsetLeft;
            	var disY = e.clientY - this.offsetTop;
            	var speedX,speedY;
            	var lastX = 0,lastY = 0;
            	var that = this;
            	document.onmousemove = function (e) {
            		var newLeft = e.clientX - disX;
            		var newTop = e.clientY - disY;
            		speedX = e.clientX - lastX;
            		speedY = e.clientY - lastY;
            		lastX = e.clientX;
            		lastY = e.clientY;
            		that.style.left = newLeft + 'px';
            		that.style.top = newTop + 'px';
            	}
            	document.onmouseup = function (e) {
            		document.onmousemove = null;
            		document.onmouseup = null;
            		move(div,speedX,speedY);
            	}
            }