JavaScript实现运动函数的封装(抛物)

        当今的生活质量越来越高,人们对于自身的身体素质也更加重视。对于运动的热情,逐渐高涨起来。

        人类的体育锻炼运动中,看见最多的就是篮球了吧。本人不会打篮球,因为篮球看着太吓人, 我的小身板也不允许我去打篮球,打篮球的过程中总会有磕磕撞撞,导致受伤。

        篮球运动的规则不就是,把球扔进篮球篮子嘛。so eazy 。再换句话说不就是大家都知道的抛物运动嘛。

        提到抛物运动,回想起高中物理,是不是大家对于打篮球就充满了‘自信’。手抬高,一扔,进了!!!

今天介绍的也是抛物运动的实现,不过不是在生活中实现它。而是在页面中实现它,而实际上在也页面上投篮的就是JavaScript。它才是本场比赛的篮球运动员。

 

 在讲抛物线运动之前,要明白抛物线运动的实质。或者将其分解为两个方向的运动。

        1.首先是竖直方向上的运动,就是单纯的高度逐渐减小的过程

        2.其次就是水平方向上的运动,也就是单纯的往一个方向位移过程。

                将这两个分支运动合起来就是我们的打篮球了。

   让我们的JavaScript上场表演吧!!!

 垂直方向:

        垂直方向的运动,在页面中就是高度的减小。

        下面是一个简单的例子:篮球的重力回弹的效果。

                

 第一阶段的过程就是球的下落过程,也就是球的高度top的不断增大。

        在top值增大的过程中也就需要,不断地给top增加一个speed步进值。

                先是基本的css和html样式和结构        

<style type="text/css">
        .cont {
            width: 1000px;
            height: 600px;
            background: #eee;
            margin: 20px auto;
            position: relative;
        }
        
        .box {
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            left: 0;
            border-radius: 50%;
        }
    </style>
<body>
    <div class="cont">
        <div class="box"></div>
    </div>
</body>

 接下来就是我们今天的主角:JavaScript登场啦!!!

        第一步是获取html当中的节点对象,才能进行操作。

<script>
    // 1 获取节点
    let contObj = document.querySelector('.cont');//篮球可以活动的范围,节点对象
    let boxObj = document.querySelector('.box');//篮球节点对象
</script>

        第二步进行我们所需要的变量的声明准备。

                其中重要的变量有:

            1. 因为地球的原因,有重力,所以在步进值speed的基础上,应该还要增加重力带来的加速度。

             2.target目标,就是篮球在范围内最大的可运动的高度(要减去球自身的高度)。

            3.要想让球的高度减少,就应该让球在反向的时候,让它的speed比原来小就可以了,所以给speed乘以一个小于1的数,就可以让反向高度变小。

// 2 设置变量
    let speed = 10; //步进值
    let g = 2; //重力的影响
    let times = ''; //清除定时器的标识符
    let target = contObj.offsetHeight - boxObj.offsetHeight; // 小球的最大目标值

第三步就是具体的实现方法 :

//球绑定点击事件
    ball.addEventListener('click', function() {
        clearInterval(timer) //防止定时器累加
        timer = setInterval(function() { //设置定时器
            speed += g; //步长增加
            if (speed < target - ball.offsetTop) { //高度小于目标高度时
                ball.style.top = ball.offsetTop + speed + 'px'; //设置球的高度样式
            } else if (speed >= target - ball.offsetTop) { //当到盒子目标高度时
                ball.style.top = target + 'px'; //让球直接到达底部
                speed = -parseInt(speed) * 0.8; //让步长变负,高度减小,球往上走
                if (Math.abs(speed) < 1) { //当步长小于1
                    clearInterval(timer); //停止
                }
            }
        }, 30)
    })

 完成上述的垂直方向的运动之后,就可以往其加上水平方向的代码了。

垂直方向和水平方向的结合:

        水平方向的原理其实和垂直方向差不多,你也可以想象将页面顺时针旋转90度。

        实现方法:

        第一步获取节点对象,同上。

        第二步准备需要的变量。因为要在水平方向上变化,肯定也需要一个水平的步进值,leftSpeed,也同样需要往左的最大范围值leftTarget,也是 篮球在范围内最大的可运动的宽度再减去球本身的宽度。增加了一个count值用来,累积运动次数,每5次增加一个重力,让它能跳更久,到底部的时间增加。

// 设置left的步进值和最大值
    var leftSpeed = 20;
    var leftTarget = 1000 - ballObj.offsetWidth;
    var count = 0; // 累计运动次数

         第三步,只需要给球在高度样式的位置添加水平位移样式即可

ballObj.style.left = leftSpeed + ballObj.offsetLeft + 'px'; //给球位移样式

在这里需要注意: 

        球可能会从水平方向滚出去。所以还需要给球设置边界:

        思路其实很简单:只需要等球到达可运动范围的最大值的时候,让它的步进值反向

            if (ballObj.offsetLeft >= leftTarget) { //当球到达最右边届
                leftSpeed = -leftSpeed; //步进值反向
            }
            if (ballObj.offsetLeft <= 0) { //当球到达最右边届
                leftSpeed = -leftSpeed; //步进值反向
            }

 综上实现得到的代码 :

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        .box {
            width: 1000px;
            height: 400px;
            margin: 50px auto;
            position: relative
        }
        
        #ball {
            width: 50px;
            height: 50px;
            background: red;
            border-radius: 50%;
            position: absolute;
            left: 0px;
            top: 0;
        }
        
        .line {
            width: 1000px;
            height: 1px;
            background: black;
            position: absolute;
            top: 300px;
            left: 0px;
        }
    </style>
</head>

<body>
    <div class="box">
        <div id="ball"></div>
        <div class="line"></div>
    </div>
</body>
<script type="text/javascript">
    // 1 获取节点
    var ballObj = document.getElementById('ball');
    var lineObj = document.querySelector('.line')
        // 2 设置top的步进值,和最大值.
        // 定时器的计数器
    var topSpeed = 5;
    var topTarget = 300 - ballObj.offsetHeight; // top的临界值
    var count = 0; // 累计运动次数
    var g = 1; // 重力值的设置

    // 设置left的步进值和最大值
    var leftSpeed = 20;
    var leftTarget = 1000 - ballObj.offsetWidth;
    //定时器标识
    var times = '';

    ballObj.onclick = function() {
        clearInterval(times); //清除定时器累加
        times = setInterval(function() {
            count++;
            if (count % 5 == 0) { //运动5次增加一个重力
                topSpeed += g; //高度步进增加
            }
            if (topSpeed + ballObj.offsetTop > topTarget) { //当大于目标值
                topSpeed = -topSpeed * 0.8; //步进变负,上升
                ballObj.style.top = topTarget; //强制到最下面
                if (Math.abs(topSpeed) < 1) clearInterval(times); //步进值小于1,清除定时器
            } else {
                ballObj.style.top = topSpeed + ballObj.offsetTop + 'px'; //给球下降的样式
                ballObj.style.left = leftSpeed + ballObj.offsetLeft + 'px'; //给球位移样式
            }
            if (ballObj.offsetLeft >= leftTarget) { //当球到达最右边届
                leftSpeed = -leftSpeed; //步进值反向
            }
            if (ballObj.offsetLeft <= 0) { //当球到达最右边届
                leftSpeed = -leftSpeed; //步进值反向
            }
        }, 30)
    }
</script>

</html>

前两个例子大同小异,方法基本相同。所以可以想办法封装一个运动函数。

        运动函数的目的就是,只要输入运动的三要素{谁运动,运动方向,目标值}。我们就能实现运动效果。

        其中获取元素的实时属性的时候,需要考虑是否是行内样式。如果不是行内样式,要添加兼容性获取样式的封装函数

        // 获取元素的非行内样式的封装函数
        function getPos(obj, attr) {//参数为对象,和属性
            if (obj.currentStyle) { // 获取css的样式
                return obj.currentStyle[attr];
            } else {
                return getComputedStyle(obj)[attr]
            }
        }

 得到元素的实时位置之后就可以进行下一步封装运动函数了。

var times = '';

        function move(ele, obj, back) { //运动函数
            clearInterval(times); //清除定时器,以免累加
            times = setInterval(function() { //定时器
                var onOff = true;
                for (let index in obj) { //遍历对象中的所有属性,index代表属性
                    var value = parseInt(getPos(ele, index)); //获取元素属性对应的样式的实时值
                    var speed = (obj[index] - value) / 10; //设置步进值
                    speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //取整,方便计算
                    if (value == obj[index]) onOff = true; // 当一个属性运动到位置,设置开关状态
                    ele.style[index] = value + speed + 'px'; //设置元素的样式
                }
                for (var i in obj) { //再次遍历对象中的所有属性
                    if (obj[i] !== parseInt(getPos(ele, i))) { //如果存在实时值和目标值不相等。
                        onOff = false; //开关状态为假
                        break;
                    }
                }
                if (onOff) { //开关为真,则清除定时器
                    clearInterval(times);
                    back && back(); //调用回调函数
                }
            }, 30)
        }
        // 获取元素的非行内样式的封装函数
        function getPos(obj, attr) {
            if (obj.currentStyle) { // 获取css的样式
                return obj.currentStyle[attr];
            } else {
                return getComputedStyle(obj)[attr]
            }
        }

调用封装运动函数的方法: 

         首先应该得到一个目标值(可以是任何数据)。target

        再比如给一个按钮绑定点击事件,开始运动。同样需要运动三要素

        ele为要运动元素名,第二个参数为对象,对象中是需要运动的属性和属性值,最后是回调函数,回调函数可以根据情况添加或者不加。

        btn.onclick = function() {
            move(ele, {
                left: target,
                height: 300
            }, function() {})
        }

 有了运动函数就可以随意添加变化的属性值了,再也不用担心要添加的变量多了!

举一个使用封装运动函数实现的例子:

         第一个要求:让红色方块移动到黑色竖线。

        第二个要求:在移动的过程中方块的高度要变化到300px。

实现步骤:

        1.首先是移动的元素是:方块。

        2.变化的属性:方块的height,方块距离屏幕的left值。

        3.目标值:height的目标值就是300px,left的目标值设为target就应该是方块的offsetLeft值减去竖线的offsetLeft值。

// 1 获取节点
        let btnObj = document.getElementById('btn'); //获取按钮节点对象
        let divObj = document.querySelector('div'); //获取方块节点对象

        // 目标值
        let target = divObj.offsetLeft - divObj.nextElementSibling.offsetLeft;

        //给按钮绑定点击事件
        btnObj.onclick = () => {
            //调用移动函数
            move(divObj, {
                left: target,
                height: 300
            }, function() {
                console.log('移到目标啦!!!');

            })
        }

 再将上面封装好的运动函数,加到点击事件后面即可完成。

运动函数的封装就完成了!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值