javascript匀速、缓冲、弹性运动及模拟重力场实现代码

2023-05-3112:40:50WEB前端开发Comments939 views字数 6873阅读模式

一、匀速运动

可以通过offsetLeft/top获取自身的实时位置,在自身的位置的基础上,通过定时器不断执行,每次在自身位置的基础上再加上一个恒定的速度值,即可形成一个简单的匀速运动。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/43738.html

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);
}

二、缓冲运动

缓冲运动也就是速度由快到慢最后停止的一个过程。而方块的自身动态位置(或透明度)与终点的位置(或透明度)的差值,刚好满足这样一个速度变化的趋势。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/43738.html

//缓冲运动
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、匀加(减)速运动文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/43738.html

通过每次给速度值加上一个固定的值,每次速度都会增加,使之变成一个匀加速的运动;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/43738.html

​​​​​​​//弹性运动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、变加(减)速运动文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/43738.html

​​​​​​​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
        }
    }
}
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/43738.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/gcs/43738.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定