一、匀速运动
可以通过offsetLeft/top获取自身的实时位置,在自身的位置的基础上,通过定时器不断执行,每次在自身位置的基础上再加上一个恒定的速度值,即可形成一个简单的匀速运动。
function move1(dom, target) {
clearInterval(dom.timer);
dom.timer = setInterval(function () {
if (dom.offsetLeft == target) {
clearInterval(dom.timer);
dom.style.left = target + 'px';
} else {
dom.style.left = dom.offsetLeft + 10 + 'px';
}
}, 30);
}
二、缓冲运动
缓冲运动也就是速度由快到慢最后停止的一个过程。而方块的自身动态位置(或透明度)与终点的位置(或透明度)的差值,刚好满足这样一个速度变化的趋势。
//缓冲运动
function move2(dom, target) {
clearInterval(dom.timer);
dom.timer = setInterval(function () {
//offsetLeft越来越大 iSpeed越来越小
var iSpeed = (target - dom.offsetLeft) / 7;
//因为offsetLeft取出来会自动取整,忽略小数,最后每次加小数的时候都会死循环将自己变成整数不变,此时将最后加的小数取整,解决这个问题;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (dom.offsetLeft == target) {
clearInterval(dom.timer);
dom.style.left = target + 'px';
} else {
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}
}, 30);
}
//缓冲运动---改变透明度
//target应是(0-100)之间的数字
function changeOpacity(dom, target) {
clearInterval(dom.timer);
dom.timer = setInterval(function () {
//因为透明度的值始终是一个0——1之间的数,速度变化太快,所以给它扩大100倍
var iCur = parseFloat(getStyle(dom, 'opacity')) * 100;
var iSpeed = (target - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (iCur == target) {
clearInterval(dom.timer);
//因为之前扩大了100倍,此处是将其值还原成0-1之间的数字
dom.style.opacity = iCur / 100;
} else {
//因为之前扩大了100倍,此处是将其值还原成0-1之间的数字
dom.style.opacity = (iCur + iSpeed) / 100;
}
}, 30);
}
//多值变化
// var target = {
// 'width': 300,
// 'opacity': 50
// }
function changeMultValue(dom, obj) {
clearInterval(dom.timer);
var iCur, iSpeed;
dom.timer = setInterval(function () {
var flag = true;
for (var prop in obj) {
if (prop == 'opacity') {
iCur = parseFloat(getStyle(dom, prop)) * 100;
} else {
iCur = parseInt(getStyle(dom, prop));
}
iSpeed = (obj[prop] - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (prop == 'opacity') {
dom.style[prop] = (iCur + iSpeed) / 100;
} else {
dom.style[prop] = iCur + iSpeed + 'px';
}
if (iCur != obj[prop]) {
flag = false;
}
}
if (flag) {
//所有值都已变化完成后,才清除定时器
clearInterval(dom.timer);
}
}, 30);
}
//多物体多值链式变化
function changeMult(dom, obj, callback) {
clearInterval(dom.timer);
var iCur, iSpeed;
dom.timer = setInterval(function () {
var flag = true;
for (var prop in obj) {
if (prop == 'opacity') {
iCur = parseFloat(getStyle(dom, prop)) * 100;
} else {
iCur = parseInt(getStyle(dom, prop));
}
iSpeed = (obj[prop] - iCur) / 7;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if (prop == 'opacity') {
dom.style[prop] = (iCur + iSpeed) / 100;
} else {
dom.style[prop] = iCur + iSpeed + 'px';
}
if (iCur != obj[prop]) {
flag = false;
}
}
if (flag) {
clearInterval(dom.timer);
typeof callback == 'function' ? callback() : '';
}
}, 30);
}
//多物体多值链式变化调用方式
// var arr = document.getElementsByTagName('div');
// var obj = {
// left: 400,
// top: 100,
// width: 400,
// height: 400,
// opacity: 50
// };
// //链式操作 第一个运动完 第二个立马开始
// arr[0].onclick = function () {
// changeMult(this, obj, function () {
// changeMult(arr[1], obj,'');
// });
// }
//获取样式
function getStyle(dom, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(dom, null)[prop];
} else {
return dom.currentStyle[prop];
}
}
三、弹性运动
1、匀加(减)速运动
通过每次给速度值加上一个固定的值,每次速度都会增加,使之变成一个匀加速的运动;
//弹性运动1:target左边 速度不断增加 target右边 速度不断减小
function move1(dom, target) {
clearInterval(dom.timer);
var iSpeed = 20;
var a = 3;
dom.timer = setInterval(function () {
if (dom.offsetLeft > target) {
iSpeed -= a;
} else {
iSpeed += a;
}
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}, 30);
}
2、变加(减)速运动
function move(dom, target) {
clearInterval(dom.timer);
var iSpeed = 20;
var a;
var u = 0.9;
dom.timer = setInterval(function () {
a = (target - dom.offsetLeft) /8;
// 这里将目标值减去当前位置,这种情况下,当距离目标值越近,分子越小,速度越慢,所以为减速运动;当超过目标值的情况下,速度变成负数,在原来speed的基础上,speed慢慢减少,直到最后变成0,然后变成负数,一旦变成负数,就会开始往反方向也就是往回运动;我们不难发现,其实当物体面向中心的目标值运动时,离得越远,速度越快。离得越近甚至超过中心点的时候,速度一直在减少;就这样一个速度变化的趋势,刚好满足我们所需要的一个弹性运动 ;
iSpeed += a;
iSpeed *= u;
//给一个相当于摩擦系数u,让其速度值越来越接近于0,运动一定程度时停止
if (Math.abs(iSpeed) < 1 && Math.abs(target - dom.offsetLeft) < 1) {
//因为当最后速度在减少到非常小的时候,每次乘0.8,会形成很长位数的小数而不会真正归零,所以我们用绝对值判断,只要小于1px我们就让他停止
clearInterval(dom.timer);
} else {
dom.style.left = dom.offsetLeft + iSpeed + 'px';
}
}, 30);
}
四、模拟重力场
var div = document.getElementsByTagName('div')[0];
div.onmousedown = function (e) {
clearInterval(div.timer);
var event = e || window.event;
var disX = event.clientX - this.offsetLeft;
var disY = event.clientY - this.offsetTop;
var lastX = this.offsetLeft;
var lastY = this.offsetTop;
document.onmousemove = function (e) {
//让方块随着鼠标移动
var event = e || window.event;
var nowX = event.clientX - disX;
var nowY = event.clientY - disY;
iSpeedX = nowX - lastX;
iSpeedY = nowY - lastY;
div.style.left = nowX + 'px';
div.style.top = nowY + 'px';
lastX = nowX;
lastY = nowY;
}
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
//让方块以最后位置时的速度作为初速度继续运动,相当于惯性运动
move(div, iSpeedX, iSpeedY)
}
}
function move(dom, iSpeedX, iSpeedY) {
//进入函数先清除定时器;防止多次触发;
clearInterval(dom.timer);
var clientX = getSize().w, clientY = getSize().h, newLeft, newTop;
var a = 6, u = 0.8;
dom.timer = setInterval(function () {
iSpeedY += a;
newLeft = dom.offsetLeft + iSpeedX;
newTop = dom.offsetTop + iSpeedY;
//运动到四周边界时,变换方向,减小速度
if (newTop > clientY - dom.offsetHeight) {
iSpeedY *= -1;//变换方向
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newTop = clientY - dom.offsetHeight;
}
if (newTop < 0) {
iSpeedY *= -1;
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newTop = 0;
}
if (newLeft > clientX - dom.offsetWidth) {
iSpeedX *= -1;
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newLeft = clientX - dom.offsetWidth;
}
if (newLeft < 0) {
iSpeedX *= -1;
iSpeedX *= 0.8;
iSpeedY *= 0.8;
newLeft = 0;
}
if (Math.abs(iSpeedX) <= 1) {
iSpeedX = 0;
}
if (Math.abs(iSpeedY) <= a * 0.8) {
iSpeedY = 0;
}
//运动到底部且两个方向上的速度都为0,让其停止,
if (iSpeedX == 0 && iSpeedY == 0 && newTop == (clientY - dom.offsetHeight)) {
clearInterval(dom.timer);
}
dom.style.left = newLeft + 'px';
dom.style.top = newTop + 'px';
}, 30);
}
//获取窗口大小
function getSize() {
if (window.innerWidth) {
return {
w: window.innerWidth,
h: window.innerHeight
}
} else if (document.body.clinetWidth) {
return {
w: document.body.clinetWidth,
h: document.body.clientHeight
}
} else {
return {
w: document.documentElement.clientWidth,
h: document.documentElement.clientHeight
}
}
}