JS_简单的运动封装

本文封装的简单例子如下:

/**
* 多属性动画
* @param {Element} element 要做动画的元素
* @param {Object} targetObj 属性目标值的对象 封装了所有要做动画的属性及其目标值
* @param {number} timeCost 动画耗时,单位毫秒
* @param {Function} callback 动画结束的回调函数
* animate(box,{left:"200px",top:"500px",opacity:0.5},3000,()=>console.log("动画结束"))*/

由于代码块中的解释已经很详细了,在此就不做过多的说明名了,看代码即可

代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #box {
            width: 100px;
            height: 100px;
            background-color: blueviolet;

            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div id="box"></div>
    <script>
        // 测试封装效果的
        box.onclick = function (e) {
            animate(box, { left: "200px", top: "500px", opacity: 0.5 }, 3000, function () { console.log("动画结束") })
        }
    </script>

    <script>
        /* 从样式属性值中截取单位 */
        // getUnit("200.123px")
        function getUnit(value) {
            // 定义所有的数字
            var digits = "0123456789."

            // 将入参先转换为string(以便计算字符数)
            value = value + ""//200px

            /* 遍历入参的每一个字符 */
            for (var i = 0; i < value.length; i++) {
                // 提取出每一个字符
                var char = value[i]

                // 看看当前字符是否是【数字字符】
                // 如果不是【数字字符】 则当前位i一直到末尾皆为单位
                if (digits.includes(char) === false) {
                    // 从当前位i一直截取到末尾 得到单位 返回之
                    return value.slice(i)
                }

            }
            return ""
        }


        // 封装一个名为animate的函数
        function animate(element, targetObj, timeCost = 1000, callback = null) {

            // 定义每帧时长为40毫秒
            var FRAEME_COST = 40

            // 计算总帧数(半帧按一帧算)3000/40
            var frames = Math.ceil(timeCost / FRAEME_COST)

            // 记录当前运行到了第几帧
            var currentFrame = 0

            // 提前拿到动画前所有CSS属性 {left:0,top:0,opacity:1...}
            var exStyles = window.getComputedStyle(element)

            /* 每个CSS属性每帧应该偏移多少 */
            // speed者 每帧偏移量也
            var speedObj = {}

            /* 计算每帧应该移动多少 */
            // key分别为 left top opacity
            for (var key in targetObj) {
                // 拿出left属性的目标值 200px
                var targetValue = targetObj[key]

                // (目标值 - 当前值)/ 总帧数
                /* 
                // 动画速度对象
                {
                    // left每帧动画速度
                    left:{
                        // 每帧偏移2
                        offset:2,

                        // 单位px
                        unit:"px"
                    },
                    top:{offset:5,unit:"px"},
                    opacity:{offset:0.005,unit:""}
                } 
                */
                speedObj[key] = {
                    // left每帧的偏移量
                    offset: (parseFloat(targetValue) - parseFloat(exStyles[key])) / frames,

                    // 将单位也揪出来
                    unit: getUnit(targetValue)
                }
            }

            /* 开始做动画 */
            var timer = setInterval(

                /* 每40毫秒执行一下这个破函数:在上一帧(frame)的基础上 所有目标样式都按动画速度speedObj[key]偏移一丢丢 */
                function () {
                    
                    // 在每帧中对每个属性按动画速度做偏移
                    for (var key in speedObj) {

                        /* 拿出left属性每帧的偏移量 */
                        var offset = speedObj[key].offset
                        
                        // 拿出left属性的单位
                        var unit = speedObj[key].unit

                        // 将元素的left设置为一个新的值(偏移了一丢丢)
                        // element.style.left = (0+2)+"px"
                        element.style[key] = 

                        // 拿出上一帧的left的值(锯掉单位)
                        parseFloat( getComputedStyle(element)[key] ) 

                        // 加上每帧应走的偏移量
                        + offset 

                        // 拼接单位
                        + unit
                    }

                    /* 看看够帧数了没有 */
                    if (++currentFrame === frames) {
                        // 帧数一满 停止动画
                        clearInterval(timer)

                        // 暴力矫正误差(将所有属性都打到目标值)
                        // {left:"200px",top:"500px",opacity:0.5}
                        for (var key in targetObj) {
                            // box.style.left = "200px"
                            element.style[key] = targetObj[key]
                        }
                    }
                },

                // 每40毫秒一帧
                FRAEME_COST
            );
        }
    
    </script>
</body>

</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值