函数需求

初始值需要获取标签的原始属性的数据

获取相应标签的属性

最终位置可控制

作为一个参数,进行输入

多种属性一起运动

使用 对象 来 存储 运动属性和最终值

每次累加的数值,不一定就是正数,甚至每次累加的数值,都有可能不是固定的数值

每次改变的数值,就设定成,一个改变的数值:( 最终值 - 初始值 ) / 完成次数
取整: 步长大于 0 向上取整,步长小于 0 向下取整

判断每一个属性是否到达最终位置,并清除相应定时器

每次生成一个定时器,就向对象中存储一个定时
对象的属性是运动属性的名称 也就是当前运动的是left 对象的属性就是left
对象的属性值是定时器的序号

判断运动停止了

每次清除定时器便删除相应的对象属性
判断创建的对象是否为空,为空则运动停止

htmlcssjs
    <button>开始</button>
    <div></div>
    * {
        margin: 0;
        padding: 0;
    }

    div {
        width: 400px;
        height: 400px;
        background: pink;
        position: fixed;
        top: 0px;
        left: 500px;
    }
    // 获取标签css样式的兼容语法函数
    // 参数1: 需要获取样式的标签对象
    // 参数2: 需要获取样式的属性名称
    function myGetStyle(element, style) {
        // 如果 浏览器 支持 window.getComputedStyle    执行结果有内容,自动转化为 true
        // 如果 浏览器 不支持 window.getComputedStyle  执行结果,为undefined,自动转化为 false
        if (window.getComputedStyle) {
            // window.getComputedStyle 转化为 true 的情况
            // 也就是 浏览器 支持 window.getComputedStyle 可以使用
            return window.getComputedStyle(element)[style];
        } else {
            // window.getComputedStyle 转化为 false 的情况
            // 浏览器不支持 window.getComputedStyle 方法  不能使用
            return element.currentStyle[style];
        }
    }

    var oDiv = document.querySelector('div');
    var oBtn = document.querySelector('button');

    // 点击button按钮,执行 运动函数
    oBtn.addEventListener('click', () => {
        move(oDiv, {left:3,top:50});

    })

    function move(element, typeObj) {
        // 定义一个对象,存储定时器
        var obj = {};
        // type就是运动的属性,也就是 left top width...
        for(let type in typeObj){
            // setInterval() 执行结果,是 定时器的编号
            // 对象[type] 就是 将 type 运动属性left等,作为对象的属性
            // 将 setInterval() 的执行结果,也就是 1,2,3... 等编号,作为对象的属性值
            obj[type] = setInterval(() => {
                // 1, 获取初始值 
                let startVal = parseInt(myGetStyle(element, type));
                // 2, 累加数值 / 步长   应该是  ( 最终值 - 初始值 ) / 设定的次数
                // 步长值 ,最终几次执行,有可能,是小数,累加的结果是不足1的
                // css样式中,对于不足1的小数像素,执行,有可能是向下取整,有可能是向上取整
                // 需要要先对,speed,步长值取整 0.5 向上取整是 1
                //                          -0.5 向下取整是 -1
                // speed 大于 0 , 向上取整, 否则 就向下取整
                let speed = ( typeObj[type] - startVal  ) / 5;

                // 对 speed 取整:
                // speed 如果 大于 0 ,就将 speed 向上取整,赋值给 speed 本身
                // speed 如果 小于 0 ,就将 speed 向下取整,赋值给 speed 本身
                speed = speed > 0 ? Math.ceil(speed) :  Math.floor(speed);

                // 初始值 累加 步长 (步长,有可能是正数,也有可能是负数)
                startVal += speed;
                // 3, 将累加之后的数值,赋值给标签css样式的属性值
                element.style[type] = startVal + 'px';

                // 4, 判断,如果到了最终目标位置,停止定时器
                // startVal 是 当前的属性值
                // typeObj[type] 是 最终属性值 top:500  left:1000
                if(startVal === typeObj[type]){
                    // 清除定时器
                    // 应该是 clearInterval(定时器编号)
                    // 当前编号存储在对象的属性中
                    // 要想获取 应该是  obj[运动属性]
                    clearInterval(obj[type]);
                    // 定出掉的定时器,就从对象中删除
                    delete(obj[type]);
                    // 如果对象是一个空对象,证明所有的定时器都清除了
                    // 证明运动真的停止了
                    // 使用: Object.keys(对象) JavaScript提供的方法
                    // 获取对象中,所有的键名,组成一个数组
                    // 当对象是一个空对象,数组就是一个空数组,length就是0
                    const objKeyArr = Object.keys(obj);
                    if(objKeyArr.length === 0){
                        // 如果数组的长度是 0 ,证明数组是一个空数组,对象是一个空对象
                        console.log('所有运动真的停止了')
                    } 
                }
            }, 30)
        }
    }

兼容px,rem,em单位

作为一个参数,进行输入

兼容透明度

如果运动属性是透明度,获取初始值,放大一个固定倍数,一般是 100倍
最终数值,步长,等都要按照倍数执行
赋值时,要去掉px单位

htmlcssjs
    <button>开始</button>
    <div></div>
    * {
        margin: 0;
        padding: 0;
    }

    div {
        width: 400px;
        height: 400px;
        background: pink;
        position: fixed;
        top: 0px;
        left: 500px;
    }
    // 获取标签css样式的兼容语法函数
    // 参数1: 需要获取样式的标签对象
    // 参数2: 需要获取样式的属性名称
    function myGetStyle(element, style) {
        // 如果 浏览器 支持 window.getComputedStyle    执行结果有内容,自动转化为 true
        // 如果 浏览器 不支持 window.getComputedStyle  执行结果,为undefined,自动转化为 false
        if (window.getComputedStyle) {
            // window.getComputedStyle 转化为 true 的情况
            // 也就是 浏览器 支持 window.getComputedStyle 可以使用
            return window.getComputedStyle(element)[style];
        } else {
            // window.getComputedStyle 转化为 false 的情况
            // 浏览器不支持 window.getComputedStyle 方法  不能使用
            return element.currentStyle[style];
        }
    }

    var oDiv = document.querySelector('div');
    var oBtn = document.querySelector('button');

    // 点击button按钮,执行 运动函数
    oBtn.addEventListener( 'click' , function(){
        move( oDiv , {left: 600 , top:400 , width:600 , height:400 , fontSize : 300 , opacity: .4} ,'',  function(){
            oDiv.style.background = 'blue';
            oDiv.style.color = '#fff';
            console.log('所有运动结束了');
        },1,1000);
    })

    // 运动函数的封装
    // 参数1 : 运动的标签对象
    // 参数2 : 运动标签对象的属性和最终值 ( 必须是 对象类型 )
    // 参数3 : 运动标签对象的单位  'px' 'rem' 'em'
    // 参数4 : 运动停止时,执行的回调函数, 可以是匿名函数,或者定义好的函数名称
    // 参数5 : 运动停止时,是否还原初始值
    // 参数6 : 运动停止时,是否还原初始值需要的时间
    function move(element , typeObj , style, fun, state, time){
        // 1.创建一个对象,存储定时器
        const IntervalObj = {};
        // 2.创建一个对象,存储数据初始状态
        const obj={};
        // 3.使用for..in 循环遍历参数
        // 自定义变量,必须使用let声明
        for( let type in typeObj ) {
            obj[ type ] =  parseInt(myGetStyle(element , type));
            // 每次循环都创建一个定时器,存储在定时器对象中
            IntervalObj[type] = setInterval( ()=>{
                // 1, 获取初始值 , 如果是 透明度 , 初始值 和 最终值 都要乘以 100
                var startVal = type === 'opacity' ? myGetStyle(element , type)*100 : parseInt( myGetStyle(element , type) );

                // 获取最终数值,如果是透明度就乘以100
                var endVal = type === 'opacity' ? typeObj[type]*100 :  typeObj[type];

                // 2, 计算步长: (最终值 - 初始值 ) / 设定的次数
                // 设定次数,不是定时器执行的次数
                var speed = ( endVal - startVal ) / 5;

                // 3, 对步长取整,大于0,向上取整,小于0,向下取整
                speed = speed > 0 ? Math.ceil( speed ) : Math.floor( speed );

                // 4, 初始值,累加步长
                startVal += speed;

                // 5, 将新的数值,设定给 标签
                // 是 透明度 除以100 设定, 不是透明度拼接px设定
                if(style == null || style == ''){
                    element.style[type] = type === 'opacity' ? startVal/100 : startVal + 'px';
                }else{
                    element.style[type] = type === 'opacity' ? startVal/100 : startVal + style;
                }

                // 6, 判断,如果 初始值累加至最终值,清除 当前运动属性,对应的定时器,停止运动
                if( startVal === endVal ){
                    // 清除 当前运动属性 对应的 定时器
                    clearInterval( IntervalObj[type] );
                    // 清除 对象中 当前属性 对应的单元
                    delete( IntervalObj[type] );
                    // 使用 Object.keys()  获取 对象中的所有属性,组成数组
                    const typeArr = Object.keys( IntervalObj );
                    // 如果数组的长度是0,对象,就是空对象,所有定时器都清除了,所有运动属性都停止了
                    if(typeArr.length === 0){
                        // 调用运动停止时,执行的函数,参数3
                        fun();
                        if(state === 1){
                            setTimeout(function(){
                                for(let type in obj){
                                    if(style == null || style == ''){
                                        element.style[type] = type === 'opacity' ? obj[type] : obj[type]+'px'
                                    }else{
                                        element.style[type] = type === 'opacity' ? obj[type] : obj[type]+'px'
                                    }
                                }
                            },time)
                        }
                    }
                }
            } , 30 );
        }
    }

动画结束是否恢复原始状态

作为一个参数,进行输入(0是不恢复状态,1是恢复状态)
将dome的属性存入一个对象当中,在结束后恢复对象属性
并再添加一个恢复原始状态的定时数

动画结束进行其他函数

作为一个参数,写入一个要执行的函数


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。