JS- 运动函数分步骤至最终

运动函数之终极版

JS- 运动函数分步骤至最终_第1张图片

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

// left,top,opacity,宽,高 都改变
oBtn.addEventListener('click', function () {
    move(oDiv, { left: 600, top: 600 , width:200 , height:400 , opacity:0}, function(){
        console.log('运动结束了');
    })
});
// 说明:
// 第一,需要使用ES6语法中的 let 声明变量
// 第二,如果是透明度,因为是小数,需要单独处理
// 第三,建立对象,存储定时器
// 第四,清除定时器器,同时删除对象中的单元
// 第五,判断对象,如果是一个空对象,证明所有运动都停止了

function move(ele, obj, callback) {
    let time = {};
    for (let type in obj) {
        let oldVal = 0;
        if (type === 'opacity') {
            oldVal = parseFloat(window.getComputedStyle(ele)[type]) * 100;
        } else {
            oldVal = parseInt(window.getComputedStyle(ele)[type]);
        }
        time[type] = setInterval(function () {
            let val = (obj[type] - oldVal) / 10;
            val = val > 0 ? Math.ceil(val) : Math.floor(val);
            oldVal += val;
            if (type === 'opacity') {
                ele.style[type] = oldVal / 100;
            } else {
                ele.style[type] = oldVal + 'px';
            }
            if (oldVal == obj[type]) {
                clearInterval(time[type]);
                delete (time[type]);
            }

            if (Object.keys(time) == 0) {
                callback();
            }
        }, 100)

    }
}

一.轮播图之运动函数1

<style>
    *{
        margin: 0;
        padding: 0;
    }
    div{
        width: 100px;
        height: 100px;
        background: pink;
        position: fixed;
        top: 100px;
        left: 0px;
    }


</style>
</head>
<body>
<button>点击</button>
<div></div>

<script>
    // 运动函数
    // 轮播图中,图片的切换,不是瞬间切换完成的
    // 而是以类似于动画/运动的方式,逐步切换完成
    // 将位移/定位效果,分多次,逐步完成

    // transition 虽然可以实现类似的效果
    // 但是对于复杂的运动,复杂的设定,是不方便支持的
    // 而且,transition过渡的兼容性,有待提高

    // 通过JavaScript,配合 定时器 来逐步完成 运动效果

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

    oBtn.addEventListener('click' , function(){
        // 定义的初始值
        var speed = 0;
        // 定时器
        var time = setInterval(function(){
            // 每次初始值,增加一个数值
            speed += 10;
            // 将这个数值定义为定位的数值
            oDiv.style.left = speed + 'px';
            // 当数值达到规定的数值时,清除定时器,终止执行
            // 运动也就终止了
            if(speed == 500){
                clearInterval(time);
            }                
        } , 30)


    })

二.轮播图之运动函数2

<style>
    * {
        margin: 0;
        padding: 0;
    }

    div {
        width: 100px;
        height: 100px;
        background: pink;
        position: fixed;
        top: 100px;
        left: 200px;
        transition: all 3s;
    }
</style>
</head>

<body>
<button>点击</button>
<div></div>

<script>
    // 解决第一个问题
    // 封装成一个函数的形式
    // 如果有初始位置,怎么办?

    // 参数1,要运动的标签
    // 参数2,要运动的方向/方式 以及 目标位置
    //       一般,目标位置与运动方式是相关的,定义对象的形式
    //       { 方式 : 位置 }  {left : 500}

    // 获取标签对象
    var oDiv = document.querySelector('div');
    var oBtn = document.querySelector('button');

    // 不愿意写点击事件,直接执行也可以
    // move(oDiv,{left:500});

    // 执行函数
    // 给按钮绑定点击事件
    // 执行的函数,是调用move()函数,并且赋值参数

    // 注意:不能在 addEventListener 参数2的位置上,直接定义move(),这样会直接调用,此时需要的是绑定,等待触发条件然后执行
    oBtn.addEventListener('click', function(){ move(oDiv,{left:500}) });
    // 直接写move函数,是直接调用move函数,不是绑定move函数
    // oBtn.addEventListener('click', move() );

    function move(ele, obj) {
        // 先通过for...in循环,来调用参数2,获取其中的执行属性和目标位置的数值
        // 目前是有obj中,有一个单元,会循环一次,生成left对应的定时器
        // 如果有obj中,有多个单元,会循环多次,生成每一个属性对应的定时器
        // 这样,每一个属性都有自己对应的定时器,便于控制和观察运动状态

        // type中存储的是,obj对象的键名,也就是left
        for(var type in obj) {
            // 初始位置,需要获取标签原始定位的数值
            // 参数2中,定义的运动属性,是谁,现在对应的就获取谁的初始数值
            // {left:500},就获取left属性对应的初始值
        
            // window.getComputedStyle 获取标签的css样式的属性值,带有px
            // 语法: window.getComputedStyle(标签对象).属性
            // 这里的属性是存储在type自定义变量中的,必须要用[]语法来解析
            var speed = parseInt(window.getComputedStyle(ele)[type]) ;
            // 定时器,每次循环都会生成一个新的定时器
            var time = setInterval(function(){
                // 初始值,加上数值
                speed += 20;
                // 将数值作为定位的数据
                // 点语法,不能解析变量,必须使用[]语法,解析存储的变量
                // 设定 标签 css , 语法是 标签对象.style[属性] = 属性值
                // type是for...in循环中,自定义的变量,用来存储对象的键名
                // 要使用时,type是变量, 对象.变量,不能解析,只能使用对象[变量]才能解析变量
                ele.style[type] = speed + 'px';

                // 当数值,达到目标值的时候,来停止定时器
                // obj是参数2,{left:500}
                // 这个500使我们的目标数值
                // 获取500这个数值,语法是 对象[属性]
                // 属性存储在变量type中,必须要[]语法才能及解析
                if (speed == obj[type]) {
                    clearInterval(time);
                }
            }, 100);
        }
    }

三.轮播图之运动函数11

JS- 运动函数分步骤至最终_第2张图片

var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');

var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];

oBtn1.addEventListener('click' , function(){
    move(oDiv,400 , 'left');
})

oBtn2.addEventListener('click' , function(){
    move(oP,300 , 'top');
})

oBtn3.addEventListener('click' , function(){
    move(oH1, 500 , 'left');
})

// 为了方便多次执行运动程序效果,将程序封装为函数
// 每次调用函数,操作的标签对象,可能是不同的标签对象
// 此时需要一个参数,来告诉函数,操作的标签对象谁

// 参数1:需要操作的,运动的标签对象
// 参数2:目标位置
// 参数3:运动方式

// 问题是: 1,参数的顺序,不可控制
//        2,参数的个数,不可控制
// 将参数2和参数3,写成对象的形式
// 也就是将 运动方式 和 目标位置 写成 对象的 属性:属性值 形式

function move(ele , target , type ){
    var speed = 0;
    var time = setInterval( function(){
        speed += 20;
        // 对象,调用变量,必须是[]语法来解析变量
        ele.style[type] = speed + 'px';
        if(speed == target){
            clearInterval(time);
        }
    } , 100)
}

四.轮播图之运动函数22

JS- 运动函数分步骤至最终_第3张图片

var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');

var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];

oBtn1.addEventListener('click' , function(){
    move(oDiv, {left:600} );
})

oBtn2.addEventListener('click' , function(){
    move(oP, {top:600});
})

oBtn3.addEventListener('click' , function(){
    move(oH1, {left:600} );
})

// 参数1:执行运动的标签对象
// 参数2:执行运动的方式和目标位置,对象的形式

function move(ele , obj ){
    // 获取对象中的属性和属性值,必须使用for...in来循环
    // 语法 for(var 变量 in 对象){程序}
    // 自定义变量中,存储的是对象的属性  对象[自定义变量]获取的就是属性值

    // type就是 top left 属性  obj[type] 就是 500 600 属性值
    for(var type in obj){
        // 运动属性,对应的初始值
        // 参数中的运动属性是谁,是top,还是left
        // 也就是 type 中 存储是什么运动属性
        // 我们就获取哪个运动属性的初始值
        // 获取的方式,是通过获取标签css样式属性的属性值
        // 应该是写成兼容的方式,暂时直接获取
        // 语法 : window.getComputedStyle(标签对象).属性
        // 1,标签对象,现在是形参ele,执行时赋值实参 oDiv,oP,oH1....
        // 2, 属性,是存储在 type 形参变量中 的数据
        //    必须使用[]语法,解析type变量
        // window.getComputedStyle(ele)[type]

        // 标签对象.style  只能获取行内样式
        // window.getComputedStyle  获取的是最终执行的样式,不区分行内,内部,外部
        //                          只要是执行的,就能拿到手
        // 执行结果有 px 单位 是 字符串形式 100px  200px ...
        // 需要获取数值部分,也就是整数部分 parseInt() 来获取

        var oldVal = parseInt(window.getComputedStyle(ele)[type]) ;
        var time = setInterval( function(){
            // 在原始数据的基础上,来执行运动
            oldVal += 20;
            // 对象,调用变量,必须是[]语法来解析变量
            ele.style[type] = oldVal + 'px';
            if( oldVal == obj[type] ){
                clearInterval(time);
            }
        } , 100)
    }
}

五.轮播图之运动函数33

JS- 运动函数分步骤至最终_第4张图片

var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');

var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];

oBtn1.addEventListener('click' , function(){
    move(oDiv, {left:205} );
})

oBtn2.addEventListener('click' , function(){
    move(oP, {top:9});
})

oBtn3.addEventListener('click' , function(){
    move(oH1, {left:7} );
})

// 参数1:执行运动的标签对象
// 参数2:执行运动的方式和目标位置,对象的形式

function move(ele , obj ){

    for(var type in obj){
        // 获取原始位置
        var oldVal = parseInt(window.getComputedStyle(ele)[type]) ;
        // 定时器
        var time = setInterval( function(){
            // 计算需要改变的数值,是多少
            // 目标位置 - 初始位置
            // 向右向下移动,就是正数,向左向上移动就是负数
            // 设定分几次完成改变数值,也就是定义每次改变的数值数值
            // 根据 终止位置,起始位置,和执行次数,计算出每次需要改变的数值
            var val = ( obj[type] - oldVal )  / 5 ;
            
            // 如果执行结果是小数,需要做取整操作
            // 通过三元运算符,给val变量进行赋值
            // 当 val > 0 时  执行的是  Math.ceil(val)  向上取整
            // 当 val <= 0 时 执行的是  Math.floor(val) 向下取整

            // 正数,当数值 0.几 时 向上取整 变的数值 是 1
            // 负数,当数值 -0.几 时 向下取整 变的数值 是 -1
            //      确保每次改变的数值,最小是1
            //      确定可以到达 目标位置,可以清除定时器
            val = val > 0 ? Math.ceil(val) : Math.floor(val) ;
            console.log(val)
            // 每次改变的是计算出来的数值
            oldVal += val;
            // console.log(oldVal);
            ele.style[type] = oldVal + 'px';
            if( oldVal == obj[type] ){
                clearInterval(time);
            }
        } , 100)
    }


}

六.轮播图之运动函数44

JS- 运动函数分步骤至最终_第5张图片

// 解决的问题:
// 监听中的参数三:运动结束之后的执行操作


var oDiv = document.querySelector('div');
var oP = document.querySelector('p');
var oH1 = document.querySelector('h1');

var oBtn1 = document.querySelectorAll('button')[0];
var oBtn2 = document.querySelectorAll('button')[1];
var oBtn3 = document.querySelectorAll('button')[2];

oBtn1.addEventListener('click' , function(){
    // 参数3,直接赋值函数
    move(oDiv, {left:205} , function(){console.log('div停止了')} );
})

oBtn2.addEventListener('click' , function(){
    // 参数3,直接赋值函数名称
    move(oP, {top:9} , fff );
})


oBtn3.addEventListener('click' , function(){
    move(oH1, {left:7} ,callback );  
})

/* oBtn3.addEventListener('click' , function(){
    move(oH1, {left:7} );   →  正常运动 但是运动停止后会在控制台中报错
}) */
// 参数1:执行运动的标签对象
// 参数2:执行运动的方式和目标位置,对象的形式

// 新增参数3:当运动停止时,执行的函数
// 这里的 callback 是形参
// 赋值的 实参,是函数的名称,或者变量名称,存储的都是函数的内存地址
// 必须要 通过() 来调用 赋值的函数 callback()

function move(ele , obj , callback ){

    for(var type in obj){
        // 获取原始位置
        var oldVal = parseInt(window.getComputedStyle(ele)[type]) ;
        // 定时器
        var time = setInterval( function(){
            // 获取需要改变数值,并且计算步长
            var val = ( obj[type] - oldVal )  / 5 ;
            // 取整,如果是正数,向上取整,如果是负数,向下取整
            // 确保,最后每次改变的最小值是1
            val = val > 0 ? Math.ceil(val) : Math.floor(val) ;
            // 每次改变的是计算出来的数值
            oldVal += val;
            // 将改变后的数值,作为属性值,赋值给css样式,实现位置的改变
            ele.style[type] = oldVal + 'px';
            // 判断,如果当前位置,也就是改变后,数值是目标位置
            if( oldVal == obj[type] ){
                // 清除定时器,终止定时器的执行,运动停止
                clearInterval(time);
                // 当清除了定时器,也就是运动终止了
                // 来调用参数3赋值的函数
                callback();
            }
        } , 100)
    }
}

function fff(){
    console.log('不管你是谁,反正你的运动停止了');
}
function callback(){
    console.log('不管你是谁,反正你的运动停止了');
}

你可能感兴趣的:(js)