JavaScript的运动与动画

本文介绍了使用JavaScript实现匀速动画波浪灯效果的代码,并展示了如何应用于轮播图的缓冲动画。通过封装的bufferAnimation函数,可以实现元素的位置、宽度、高度、透明度和层高的平滑变化。此外,文章还涵盖了滚动切换、透明度切换、无缝轮播和定时器带焦点的轮播图实现方法,提供了详细的代码示例。

匀速动画波浪灯案例

<script>

        function animate(el, target) {

            clearInterval(el.timer);

            el.timer = setInterval(() => {

                let current = el.offsetWidth;

                //当前位置

                let steps = target > current ? 10 : -10;

                //步长

                el.style.width = current + steps + "px";

                //新的位置=当前位置+步长

                if (Math.abs(target - el.offsetWidth) <= Math.abs(steps)) {

                    el.style.width = target + "px";

                    clearInterval(el.timer);

                }

            }, 30);

        }

        var oLis = document.querySelectorAll("li");

        oLis.forEach((item) => {

            //遍历每一个

            item.addEventListener("mouseenter", (e) => {

                const { target } = e;

                //结构解析

                if (target.children[0].nodeName !== "DIV") {

                    return;

                }

                animate(target.children[0], 100);

            });

            item.addEventListener("mouseleave", function (e) {

                const { target } = e;

                if (target.children[0].nodeName !== "DIV") {

                    return;

                }

                animate(target.children[0], 0);

            });

        });

    </script>

缓冲动画div任意位置移动

<script>

        //div位置变化 以缓冲运动变化

        //获取div

        var div = document.querySelector('div')

        //运动三要素

        //当前值

        let current = parseFloat(getStyle(div).left)

        //目标值

        let target = 500

        //给div添加点击事件

        div.onclick = function () {

            var timer = setInterval(() => {

                if (current >= target) {

                    clearInterval(timer)

                } else {

                    //变化值 (目标值 - 当前值)/10  10 100 9 81 (必须取整)

                    let step = Math.ceil((target - current) / 10)

                    //控制current的变化

                    current += step

                    //设置给对应的div

                    div.style.left = current + 'px'

                    //如果到了就停止

                }

            }, 50)

        }

        //封装一个方法获取对应的样式(获取所有样式)

        function getStyle(element) {

            if (window.getComputedStyle) {

                return window.getComputedStyle(element, '')

            } else {

                return element.currentStyle

            }

        }

适用于轮播图的封装JavaScript

//element表示当前的元素 target表示目标对象 callbackFn表示传入的回调函数

function bufferAnimation(element, targetObj,callbackFn) {

    //如果element为undefined就直接报错

    if(!element){

        throw new Error('元素不能缺少')

    }

    //清除上一次定时器影响

    clearInterval(element.timer)

    //给元素对象添加一个属性为timer他是一个定时器

    element.timer = setInterval(() => {

        var flag = true

        //遍历对象

        for (let key in targetObj) {

            //取出当前值

            let current = parseFloat(getStyle(element)[key])

            //取出目标值

            let target = targetObj[key]

            //判断当前如果是位置的变化及对应的宽度高度的变化

            if(key=='width' || key == 'height' || key == 'left' || key == 'top'){

                //步长 负值向下取整 正值向上取整

                var step = target-current>0?Math.ceil((target - current) / 10):Math.floor((target - current) / 10)

                current += step

                element.style[key] = current + 'px'

            }

            //如果是透明度的变化

            if(key == 'opacity'){

                //步长 负值向下取整 正值向上取整

                var step = target-current>0?Math.ceil((target - current) * 1000 / 10):Math.floor((target - current)*1000 / 10)

                current += step / 1000

                element.style[key] = current

            }

            //如果是层高直接赋值

            if(key == 'zIndex'){

                element.style[key] = target

            }

            //如果没有完成就是false

            if(current != target){

                flag = false

            }

        }

        //如果全部走完了就清除

        if(flag){

            clearInterval(element.timer)

            //调用回调函数 如果传入的参数是函数

            if(typeof callbackFn == 'function'){

                callbackFn()

            }

        }

    },20)

}

//封装一个方法获取对应的样式(获取所有的样式)

function getStyle(element) {

    if (window.getComputedStyle) {

        return window.getComputedStyle(element, '')

    } else {

        return element.currentStyle

    }

}

1.滚动切换轮播图

 //核心

        //对应图的切换

        //滚动切换 (更改大盒子的位置)

        //透明度切换 (更改对应的透明度)

        //图片切换 (直接变化对应的图片)

        //1.获取显示的盒子

        var showBox = document.querySelector('.showBox')

        //获取显示盒子的宽度

        var showWidth = parseFloat(getStyle(showBox).width)

        //获取ul ul是主要切换的容器

        var wrap = document.querySelector('.wrap')

        //封装一个自动轮播方法

        function autoMove() {

            //切换图片定时器

            var i = 0

            var timer = setInterval(() => {

                i++ //这个i就是控制对应的位置的下标

                //到达最后 切换到第一个

                if (i == wrap.children.length) {

                    i = 0

                }

                //移动对应的ul 0 -400 -800

                //距离等于 当前下标+对应显示盒子的宽度*-1

                var distance = i * showWidth * -1

                bufferAnimation(wrap, { left: distance })

            }, 1000)

        }

        //调用自动移动方法

        autoMove()

    </script>

2.透明轮播图

var wrap = document.querySelector('.wrap')

        //封装一个自动轮播方法

        function autoMove() {

            //切换图片定时器

            var i = 0

            var timer = setInterval(() => {

                //该透明度 将之前的全部设置为0 先要将对应的透明度改为1

                bufferAnimation(wrap.children[i], { opacity: 0}, function () {

                    i++ //这个i就是控制对应的位置的下标

                    //到达最后 切换到第一个

                    if (i == wrap.children.length) {

                        i = 0

                    }

                    //自己的透明度改为1

                    bufferAnimation(wrap.children[i], { opacity:1})

                })

            }, 1000)

        }

        //调用自动移动方法

        autoMove()

3.无缝轮播图

//核心

        //对应图的切换

        //滚动切换 (更改大盒子的位置)

        //透明度切换 (更改对应的透明度)

        //图片切换 (直接变化对应的图片)

        //1.获取显示的盒子

        var showBox = document.querySelector('.showBox')

        //获取显示盒子的宽度

        var showWidth = parseFloat(getStyle(showBox).width)

        //获取ul ul是主要切换的容器

        var wrap = document.querySelector('.wrap')

        //拷贝第一张图加到最后

        //克隆第一张

        var firstLi=wrap.children[0].cloneNode(true)

        //将克隆的元素加到ul

        wrap.appendChild(firstLi)

        //封装一个自动轮播方法

        function autoMove() {

            //切换图片定时器

            var i = 0

            var timer = setInterval(() => {

                i++ //这个i就是控制对应的位置的下标

                //移动对应的ul 0 -400 -800

                //距离等于 当前下标+对应显示盒子的宽度*-1

                var distance = i * showWidth * -1

                //执行动画

                bufferAnimation(wrap, { left: distance },()=>{

                    if (i ==wrap.children.length-1) {

                        //立即设置位置

                        wrap.getStyle.left=0

                        i=0

                    }

                })

            }, 1000)

        }

        //调用自动移动方法

        autoMove()

4.定时器带焦点轮播图

//获取显示盒子

var showBox = document.querySelector('.showBox')

//获取显示盒子的宽度

var showWidth = parseFloat(getStyle(showBox).width)

//获取ul(需要切换位置的容器)

var wrap = document.querySelector('.wrap')

//获取焦点的盒子

var cirList = document.querySelector('.cirList')

//获取箭头的盒子

var arrow = document.querySelector('.arrow')

//变化的下标

var i = 0

//焦点取值的下标

var index = 0

//定时器

var timer

//调用init的方法

init()

//调用自动移动的方法

autoMove()

//给showBox添加移入事件

showBox.onmouseenter = function () {

    //清除定时器

    clearInterval(timer)

    //显示箭头的盒子

    arrow.style.display = 'block'

}

//移出继续执行

showBox.onmouseleave = function () {

    //调用轮播

    autoMove()

    //隐藏

    arrow.style.display = 'none'

}

//给箭头添加事件

Array.from(arrow.children).forEach((v, i) => {

    v.onclick = (e) => {

        e = e || window.event

        //禁止a标签默认行为

        e.preventDefault();

        move(wrap, showWidth, i)

    }

})

//给cirList下面的li添加点击事件 事件委托机制

cirList.onclick = function (e) {

    e = e || window.event

    //判断当前操作的元素是否为li

    if (e.target.tagName == 'LI') {

        //获取当前点击的li的下标

        let clcikIndex = Array.from(cirList.children).findIndex((v) => {

            //如果当前操作的对象是遍历的对象那么返回出去

            return v == e.target

        })-1

        //改变对应位置及下标

        index = clcikIndex

        i = clcikIndex

        //调用move移动

        move(wrap, showWidth)

    }

}

//初始化生成焦点的方法

function init() {

    //拷贝之前生成对应的焦点

    Array.from(wrap.children).forEach((v, i) => {

        //在第一个焦点添加一个class名字为selected

        if (i == 0) {

            cirList.innerHTML += `<li class='selected'></li>`

        } else {

            //生成对应的焦点加入到cirList里面

            cirList.innerHTML += `<li></li>`

        }

    })

    //拷贝第一张图加到最后

    //克隆第一个li

    var firstLi = wrap.children[0].cloneNode(true)

    //将克隆的元素加入到ul

    wrap.appendChild(firstLi)

}

//封装一个autoMove的函数

function autoMove() {

    //切换图片的定时器

    timer = setInterval(() => {

        move(wrap, showWidth)

    }, 2000)

}

//封装一个焦点变化的函数 传入的index表示当前要设置的焦点

function changeCir(index) {

    //排他思维

    //先将所有的class清除

    Array.from(cirList.children).forEach((li) => {

        li.className = ''

    })

    //再给自己添加对应的样式

    cirList.children[index].className = 'selected'

}

//抽取方法 x轴移动 移动的元素 变化i值 移动的宽度 对应的方向(默认为正方向)

function move(element, showWidth, isAsc = true) {

    //先检索区间

    rangeCheck(element, isAsc)

    //再进行i值变化

    if (isAsc) {

        i++

        index++

    } else {

        i--

        index--

    }

    //焦点切换及区间检索

    rangeCheckCir(element)

    //执行动画

    //移动对应的ul 0 -400 -800

    //距离等于 当前下标*对应显示盒子的宽度*-1

    var distance = i * showWidth * -1

    bufferAnimation(element, {

        left: distance

    }, () => {

    })

}

//区间检索i下标

function rangeCheck(element, isAsc) {

    //到达最后下标

    if (i >= element.children.length - 1 && isAsc) {

        //i的值重新变成0

        i = 0

    }

    if (i <= 0 && !isAsc) {

        //立即设置位置 到第一张设置位置为最后一张

        i = element.children.length - 1

    }

    //设置位置

    element.style.left = i * showWidth * -1 + 'px'

}

//区间检索对应的焦点下标值

function rangeCheckCir(element) {

    //判断焦点下标

    if (index < 0) { //8张图 下标为 0-7 7个焦点 下标 0-6

        index = element.children.length - 2

    }

    if (index > element.children.length - 2) {

        index = 0

    }

    //更改焦点

    changeCir(index)

}

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值