美文网首页
JavaScript--运动

JavaScript--运动

作者: 蒜泥捣莓 | 来源:发表于2022-08-15 19:03 被阅读0次

    一、概述

    运动主要是动画的操作,主要是操作某个document元素的属性变化(位置变化)

    二、运动主要的原理及步骤

    原理:

    使用开启定时器setInterval()/setTimeout() 和 清除定时器clearInterval()/clearTimeout来控制运动, 其中setInterval()方法可以让物体动起来, 而clearInterval()方法可以让运动停止; 在定时器过程中不断更改需要改变的值(如: 位置left/top, 宽高width/height,透明opacity:0.9,filter:alpha(opacity=90)等)

    步骤:

    • 使用定时器来定时更改对应的内容
    • 实时获取对应的元素的属性及相关内容
    • 判断是否到达目标位置(到达后清除定时器)

    三、匀速运动

    概述:匀速运动的本质就是每次变化值都是同一个

    示例
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                position: relative;
                width: 100px;
                height: 100px;
                background-color: red;
            }
        </style>
    </head>
    <body>
        <button>匀速运动</button>
        <div></div>
        <script>
            //获取div
            var btn = document.querySelector('button')
            var div = document.querySelector('div')
            btn.onclick = ()=>{
                //使用定时器
                var step = 10
                var target = 500
                var current = 0
                var timer = setInterval(() => {
                    //在定时器内控制div的位置变化
                    current += step //当前位置变化
                    div.style.left = current + 'px' //设置位置
                    //当到达目标位置清除定时器
                    if(current == target){
                        clearInterval(timer)
                    }
                    
                }, 20);
            }
        </script>
    </body>
    </html>
    

    四、缓冲运动

    概述: 缓冲运动的本质就是每次变化的值越来越小

    示例
    //缓冲运动
    //获取div和对应的按钮
    var btns = document.querySelectorAll('button')
    var box = document.querySelector('div')
    btns[0].onclick = ()=>{
        //获取当前位置
        var current = parseInt(getStyle(box,'left'))
        //定义步长和对应的目标位置
        var step = 10 //初始步长
        var target = 500 //目标位置
        //定时器
        var timer = setInterval(() => {
            //控制步长的变化 离目标会越来越小 把步长和这个距离绑定
            step = (target - current)/20 > 0 ? Math.ceil((target - current)/20) : Math.floor((target - current)/20) 
            //控制当前位置的变化
            current += step
            //给当前位置赋值
            box.style.left = current + 'px'
            //到达目标位置清除定时器
            if(current == target){
                clearInterval(timer)
            }
        }, 80);
    }
    

    匀速移动和缓冲移动的封装

    //获取样式的方法
    function getStyle(ele, attr) {
        return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr]
    }
    //缓冲动画为true 不传就是匀速
    function move(ele, target, isBuffer) {
        //获取当前位置
        var current = parseInt(getStyle(ele, 'left'))
        //定义步长和对应的目标位置
        var step = target - current > 0 ? 10 : -10
        //定时器
        var timer = setInterval(() => {
            if (isBuffer) {
                //控制步长的变化 离目标会越来越小 把步长和这个距离绑定
                step = (target - current) / 20 > 0 ? Math.ceil((target - current) / 20) : Math.floor((target - current) / 20) 
            }
            //控制当前位置的变化
            current += step
            //给当前位置赋值
            ele.style.left = current + 'px'
            //到达目标位置清除定时器
            if (current == target) {
                clearInterval(timer)
            }
        }, 20)
    }
    

    透明度变化

    //透明度变化
    function opacityAction(box,target){
        //获取当前的透明度
        //设置步长及对应的目标位置
        var step
        var current = parseFloat(getStyle(box, 'opacity'))
        //开启定时器
        var timer = setInterval(() => {
            // step =  target-current>0?0.1:-0.1
            //当透明度到达目标位置清除定时器
            if(Math.abs(target-current) <= step){
                clearInterval(timer)
            }
            // 最小值 0.01
            step = (target-current)*100/10 > 0 ? Math.ceil((target-current)*100/10)/100 : Math.floor((target-current)*100/10)/100
            //控制透明度的变化
            current += step
            box.style.opacity = current
        }, 20);
    }
    

    宽度变化

    //获取按钮及div
    var box = document.querySelector('div')
    var btn = document.querySelector('button')
    btn.onclick = ()=>{
        //获取开始的宽度 以及步长
        var current = parseFloat(getStyle(box,'width'))
        var step 
        var target = 500
        //设置目标位置
        var timer = setInterval(() => {
            //判断是否到达目标位置
            if(Math.abs(target-current)  <= step){
                clearInterval(timer)
            }
            //设置步长
            // step = target - current > 0 ? 10 : -10
            step = (target-current )/10 > 0 ? Math.ceil((target-current)/10) : Math.floor((target-current)/10)
            //设置当前的位置
            current += step
            box.style.width = current + 'px'
    
        }, 20);
    }
    //获取样式的方法
    function getStyle(ele, attr) {
        return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr]
    }
    

    简易封装move.js

    //获取样式的方法
    function getStyle(ele, attr) {
        return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr]
    }
    //缓冲动画为true 不传就是匀速
    function move(ele, target, isBuffer = false) {
        clearInterval(ele.timer) //清除之前的定时器影响
        //针对于px为单位的 width,height,left,top
        //opacity不需要px 
        //zIndex不需要动画
        //获取target对象里面的所有的key
        ele.timer = setInterval(() => {
            var flag = true
            for (let key in target) {
                //获取当前位置
                var current = parseFloat(getStyle(ele, key)) ? parseFloat(getStyle(ele, key)) : 0
                //定义步长和对应的目标位置
                if(key == 'opacity'){
                    var step = target[key] - current > 0 ? 0.01 : -0.01
                    }else{
                        var step = target[key] - current > 0 ? 10 : -10
                        }
                //定时器
                if (key == 'zIndex') { //层级
                    ele.style[key] = target[key] //直接设置
                } else {
                    //没有到达设置为false
                    if (Math.abs(target[key] - current ) > step) {
                        flag = false
                    }
                    if (isBuffer) { //如果是缓冲的
                        if (key == 'opacity') { //透明度
                            // 最小值 0.01
                            step = (target[key] - current) * 100 / 10 > 0 ? Math.ceil((target[key] - current) * 100 / 10) / 100 : Math.floor((target[key] - current) * 100 / 10) / 100
                        } else { //其他的
                            //控制步长的变化 离目标会越来越小 把步长和这个距离绑定
                            step = (target[key] - current) / 10 > 0 ? Math.ceil((target[key] - current) / 10) : Math.floor((target[key] - current) / 10)
                        }
                    }
                    //控制当前位置的变化
                    current += step
                    //给当前位置赋值
                    if (key != 'opacity') {
                        ele.style[key] = current + 'px'
                    } else {
                        ele.style[key] = current
                    }
                }
            }
            if (flag) {
                clearInterval(ele.timer)
            }
        }, 20)
    }
    

    五、链式动画

    链式动画 等一个完成以后再进行某个操作 (通过回调函数来实现)

    //获取样式的方法
    function getStyle(ele, attr) {
        return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr]
    }
    //缓冲动画为true 不传就是匀速
    function move(ele, target, isBuffer = true,callback) {
        clearInterval(ele.timer) //清除之前的定时器影响
        //针对于px为单位的 width,height,left,top
        //opacity不需要px 
        //zIndex不需要动画
        //获取target对象里面的所有的key
        ele.timer = setInterval(() => {
            var flag = true
            for (let key in target) {
                //获取当前位置
                var current = parseFloat(getStyle(ele, key)) ? parseFloat(getStyle(ele, key)) : 0
                //定义步长和对应的目标位置
                if(key == 'opacity'){
                    var step = target[key] - current > 0 ? 0.01 : -0.01
                }else{
                    var step = target[key] - current > 0 ? 10 : -10
                }
                //定时器
                if (key == 'zIndex') { //层级
                    ele.style[key] = target[key] //直接设置
                } else {
                    //没有到达设置为false
                    if (Math.abs(target[key] - current ) > step) {
                        flag = false
                    }
                    if (isBuffer) { //如果是缓冲的
                        if (key == 'opacity') { //透明度
                            // 最小值 0.01
                            step = (target[key] - current) * 100 / 10 > 0 ? Math.ceil((target[key] - current) * 100 / 10) / 100 : Math.floor((target[key] - current) * 100 / 10) / 100
                        } else { //其他的
                            //控制步长的变化 离目标会越来越小 把步长和这个距离绑定
                            step = (target[key] - current) / 10 > 0 ? Math.ceil((target[key] - current) / 10) : Math.floor((target[key] - current) / 10)
                        }
                    }
                    //控制当前位置的变化
                    current += step
                    //给当前位置赋值
                    if (key != 'opacity') {
                        ele.style[key] = current + 'px'
                    } else {
                        ele.style[key] = current
                    }
                }
            }
            if (flag) {
                clearInterval(ele.timer)
                //如果你的回调是一个函数就执行
                if(callback instanceof Function){
                    callback()
                }
            }
        }, 20)
    }
    

    回到顶部的实现

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div{
                height: 1500px;
            }
            button{
                display: none;
                position: fixed;
                bottom: 50px;
                right: 30px;
            }
        </style>
    </head>
    <body>
        <div></div>
        <button>回到顶部</button>
        <script src="./move.plus.js"></script>
        <script>
            //滚动栏 监听滚动栏滚动
            var btn = document.querySelector('button')
            window.onscroll = function(){
                if(window.scrollY >= 500){
                    btn.style.display = 'block'
                    move(btn,{opacity:1})
                }else{
                    move(btn,{opacity:0})
                }
            }
            btn.onclick = function(){
                //将对应的滚动栏 以缓冲动画运动到对应的位置0
                var target = 0
                var current = window.scrollY
                var step = (target - current)/10 > 0 ? Math.ceil((target - current)/10) : Math.floor((target - current)/10)
                var timer = setInterval(() => {
                    current += step
                    window.scrollTo(0,current)
                    if(current == target){
                        clearInterval(timer)
                    }
                }, 20);
            }
        </script>
    </body>
    </html>
    

    六、 第三方 move.js

    主要使用

    to 从当前位置到达某个位置(x,y)

    set 设置相关样式 (样式名,样式值)

    end 结束当前动画

    duration 运动的时长(默认时长为0.5s)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .box{
                width: 100px;
                height: 100px;
            }
        </style>
    </head>
    <body>
        <div class="box"></div>
        <script src="./move.min.js"></script>
        <script>
            move('.box')
            .to(500, 200) //到某个位置 to到某个位置  set 设置相关样式 then回调  end 表示结束 duration 总时长
            // .rotate(180)
            // .scale(.5)
            .set('background-color', '#888')
            .set('border-color', 'black')
            .duration('2s')
            // .skew(50, -10)
            // .then()//回调
            //     .set('opacity', 0)
            //     .duration('0.3s')
            //     .scale(0.1)
            //     .pop()
            .end();
        </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:JavaScript--运动

          本文链接:https://www.haomeiwen.com/subject/naslgrtx.html