来源渡一笔记
匀加速运动
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
弹性运动(匀加速)
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距离不成正比,非弹簧运动。
弹性运动(理想弹簧运动)
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
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
首先想到的就是缓冲运动中的取整
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
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
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);
}
其实这都需要时不时的写一写,有好处。
模拟边界(匀速运动)(速度反方向问题)
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);
}
模拟重力场(拖拽)
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);
}
}