Web APIs(六)

缓慢动画的原理

匀速动画=盒子当前的位置+固定的值

缓慢动画=盒子当前的位置+变化的值

思路

  • 核心算法:(目标值-当前的位置)/n 作为每次移动的步长
  • 停止的条件:让盒子当前的位置等于目标的位置,就停止定时器

在这里插入图片描述


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>缓慢动画的原理</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        img {
            position: absolute;
            display: block;
            width: 200px;
            height: 200px;
            margin-top: 20px;
            border: 1px solid red;
            border-radius: 50%;
        }
        button:nth-of-type(1) {
            margin-left: 100px;
        }
        button:nth-of-type(2) {
            margin-left: 1200px;
        }
    </style>
</head>
<body>
<button>前进</button>
<button>后退</button>
<img src="./image/uos.jpg" alt="">

</body>
<script>
    let image = document.querySelector('img');
    let bth = document.querySelectorAll('button');

    function  animate(obj,target) {
        clearInterval(obj.timer)
        obj.timer = setInterval(function (){
            var step = (target - obj.offsetLeft) /10
            if(obj.offsetLeft == target){
                clearInterval(obj.timer)
            }
            obj.style.left = obj.offsetLeft+step +'px';
        },15)
    }


    bth[0].addEventListener('click',function () {
        animate(image,1250)
    })
    bth[1].addEventListener('click',function (){
        animate(image,0)
    })
</script>
</html>


在这里插入图片描述

缓慢动画之进阶

步长值需取整

  • 如果是正值 则往大取整
  • 如果是负值 则往小取整
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>缓慢动画之进阶</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        img {
            position: absolute;
            display: block;
            width: 200px;
            height: 200px;
            margin-top: 20px;
            border: 1px solid red;
            border-radius: 50%;
        }
        button:nth-of-type(1) {
            margin-left: 100px;
        }
        button:nth-of-type(2) {
            margin-left: 1200px;
        }
    </style>
</head>
<body>
<button>前进</button>
<button>后退</button>
<img src="./image/uos.jpg" alt="">

</body>
<script>
    let image = document.querySelector('img');
    let bth = document.querySelectorAll('button');

    function  animate(obj,target) {
        clearInterval(obj.timer)
        obj.timer = setInterval(function (){
            //步长值需要取整 如果是正值 则往大取整 如果是负值 则往小取整
            var step = (target - obj.offsetLeft) /10;
            step = step>0?Math.ceil(step):Math.floor(step)
            if(obj.offsetLeft == target){
                clearInterval(obj.timer)
            }
            obj.style.left = obj.offsetLeft+step +'px';
        },15)
    }


    bth[0].addEventListener('click',function () {
        animate(image,1250)
    })
    bth[1].addEventListener('click',function (){
        animate(image,0)
    })
</script>
</html>

在这里插入图片描述

缓慢动画之添加回调函数

回调函数:被作为参数传递的函数

核心思路:回调函数要添加到定时器结束的位置

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>缓慢动画之添加回调函数</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        img {
            position: absolute;
            display: block;
            width: 200px;
            height: 200px;
            margin-top: 20px;
            border: 1px solid red;
            border-radius: 50%;
        }
        button:nth-of-type(1) {
            margin-left: 100px;
        }
        button:nth-of-type(2) {
            margin-left: 1200px;
        }
      .big {
            width: 400px;
            height: 400px;
        }
        .small {
            width: 100px;
            height: 100px;
        }
    </style>
</head>
<body>
<button>前进</button>
<button>后退</button>
<img src="./image/uos.jpg" alt="">

</body>
<script>
    let image = document.querySelector('img');
    let bth = document.querySelectorAll('button');

    function  animate(obj,target,callback) {
        clearInterval(obj.timer)
        obj.timer = setInterval(function (){
            //步长值需要取整 如果是正值 则往大取整 如果是负值 则往小取整
            var step = (target - obj.offsetLeft) /10;
            step = step>0?Math.ceil(step):Math.floor(step)
            if(obj.offsetLeft == target){
                clearInterval(obj.timer)
            };
            //回调函数写在定时器结束的位置上
            if(callback){
                callback()
            }
            obj.style.left = obj.offsetLeft+step +'px';
        },15)
    }


    bth[0].addEventListener('click',function () {
        animate(image,1250,function (){
            image.className='big'
        })
    })
    bth[1].addEventListener('click',function (){
        animate(image,0,function (){
            image.className='small'
        })
    })
</script>
</html>

在这里插入图片描述

animate动画函数

animate.js文件


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>引用animate函数</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .slider-bar {
            position: fixed;
            bottom: 20px;
            right: 0;
            width: 40px;
            height: 40px;
            color: #ffffff;
            text-align: center;
            line-height: 40px;

        }
        .con {
            position: absolute;
            top: 0;
            left: 0;
            width: 200px;
            height: 40px;
            background-color: purple;
            z-index: -1;
        }
    </style>
</head>
<script src="animate.js"></script>
<body>
    <div class="slider-bar">
        <span></span>
        <div class="con">问题反馈</div>
    </div>
</body>
<script>
    //获取元素
    let  slider_bar = document.querySelector('.slider-bar');
    let con = document.querySelector('.con');

    slider_bar.addEventListener('mouseenter',function (){
        animate(con,-160,function (){
            slider_bar.children[0].innerHTML = '← '
        })
    });
    slider_bar.addEventListener('mouseleave',function (){
        animate(con,0,function (){
            slider_bar.children[0].innerHTML = '→'
        })
    })
</script>
</html>

在这里插入图片描述

轮播图

轮播图也称为焦点图,是网页中比较常见的网页特效。

功能

在这里插入图片描述

animate.js

function animate(obj, target, callback) {
    // 清除以前的定时器,只保留当前的计时器

    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        // 如果步长为正值 则取大  如果步长为负值 则取小
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);

        // 判断:如果目标对象的位置等于目标位置,则清除定时器
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            // 回调函数要添加到定时器结束的位置
            if (callback) {
                callback()
            }
        }
        obj.style.left = obj.offsetLeft + step + "px"
    }, 15);

}


主文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul, ol, li {
            list-style: none;
        }

        .focus {
            position: relative;
            overflow: hidden;
            width: 960px;
            height: 540px;
            margin: 20px auto;
        }

        .arr-left,
        .arr-right {
            display: none;
            position: absolute;
            width: 32px;
            height: 32px;
            padding: 4px;
            background-color: #ffffff;
            opacity: 0.5;
            z-index: 2;
            transform: translate(0%, -50%);
        }

        .arr-left {
            left: 0;
            top: 50%;
            border-radius: 0px 50px 50px 0px;
        }

        .arr-right {
            right: 0;
            top: 50%;
            border-radius: 50% 0px 0px 50%;
        }

        .focus ul.picture {
            position: absolute;
            top: 0;
            left: 0;
            width: 600%;
        }

        .focus ul.picture li {
            float: left;
        }

        ul.picture img {
            width: 960px;
        }

        ol {
            position: absolute;
            left: 50%;
            bottom: 20px;
            transform: translate(-50%, -50%);
        }

        ol li {
            float: left;
            width: 16px;
            height: 16px;
            margin: 4px;
            border-radius: 50%;
            background-color: #fff;
            opacity: 0.5;
        }

        .current {
            background-color: blue !important;
        }
    </style>
</head>
<script src="animate.js"></script>
<body>
<div class="focus">
    <a href="javascript:;" class="arr-left"><img src="./image/arr-l.png" alt=""></a>
    <a href="javascript:;" class="arr-right"><img src="./image/arr-r.png" alt=""></a>

    <ul class="picture">
        <li><a href="javascript:;"><img src="image/focus1.jpg" alt=""></a></li>
        <li><a href="javascript:;"><img src="image/focus2.jpg" alt=""></a></li>
        <li><a href="javascript:;"><img src="image/focus3.jpg" alt=""></a></li>
        <li><a href="javascript:;"><img src="image/focus4.jpg" alt=""></a></li>
    </ul>

    <ol>

    </ol>
</div>
</body>
<script>
    //获取元素
    let arr_l = document.querySelector('.arr-left');
    let arr_r = document.querySelector('.arr-right');
    let focus = document.querySelector('.focus');
    let focusWidth = focus.offsetWidth;
    //1.鼠标经过焦点图 左右箭头显示  鼠标离开焦点图 左右箭头隐藏
    focus.addEventListener('mouseenter', function () {
        arr_l.style.display = 'block';
        arr_r.style.display = 'block';
        clearInterval(timer);
        time = null; //清除定时器变量
    })
    focus.addEventListener('mouseleave', function () {
        arr_l.style.display = 'none';
        arr_r.style.display = 'none';
        timer = setInterval(() => {
            arr_r.click()
        }, 2000)

    })
    //2.动态创建li 有几张图片就创建几个li
    let ul = focus.querySelector('.picture');
    let ol = document.querySelector('ol');
    for (let i = 0; i < ul.children.length; i++) {
        let li = document.createElement('li');
        //为每个li设置自定义属性
        li.setAttribute('index',i)
        ol.appendChild(li);
        //3.点击当前li 并使用排他思想
        li.addEventListener('click', function () {
            //清除所有li的默认样式
            for (let i = 0; i < ol.children.length; i++) {
                ol.children[i].className = ''
            }
            //单独为当前li设置样式
            this.className = 'current'
            //4.点击li 图片移动至相对应的距离
            let index = this.getAttribute('index');
            //把index的值赋值给index及circle 以便点击点击ol中的li 使图片与ol中的li保持同步
            num = index;
            circle = index;
            animate(ul, -index * focusWidth)
        });

    }
    ol.children[0].className = 'current';
    //5.深克隆ul中的第一个li 并追加到ul后面
    let firstLi = ul.children[0].cloneNode(true);
    ul.appendChild(firstLi)

    //6.点击右侧按钮 图片相对应的滚动一张 利用无缝滚动原理 克隆第一张图片追加到ul后面 声名一个变量num 来实现自增效果;
   let num = 0;
    let circle = 0;
    //开启节流阀
   let flag = true;
    arr_r.addEventListener('click', function () {
        if (flag) {
            flag = false;
            console.log(flag)
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0
            }
            num++;
            animate(ul, -num * focusWidth, function () {
                flag = true;
            });
            //7.点击右侧按钮 图片及下面的小圆圈相对应滚动
            circle++;
            if (circle == ol.children.length) {
                circle = 0;
            }


        }
        circleChange()
    })
    //7.点击左侧按钮 图片相对应的滚动一张 利用无缝滚动原理 克隆第一张图片追加到ul后面 声名一个变量num 来实现自增效果;

    arr_l.addEventListener('click', function () {
        if (flag) {
            flag = false;
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * focusWidth;

            }
            ;
            num--;
            animate(ul, -num * focusWidth, function () {
                flag = true;
            });
            //7.点击右侧按钮 图片及下面的小圆圈相对应滚动
            circle--;
            if (circle < 0) {
                circle = ol.children.length-1 ;
            }
            circleChange()
        }
    })

    //封装一个清除circle类的函数
    function circleChange() {
        //清除所有circle的current类名
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = ''
        }
        //留下当前的circle的current类名
        ol.children[circle].className = 'current'
    }

    //开启定时器功能
    let timer = setInterval(() => {
        arr_r.click()
    }, 2000)


</script>
</html>

在这里插入图片描述

节流阀

防止轮播图按钮连续点击造成播放过快。

目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。

核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。

aniamte动画函数之返回顶部

滚动窗口至页面中的任意位置 window.scroll(x,y)

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .slider-bar {
            position: absolute;
            top: 300px;
            left: 50%;
            /* 版心的一半 */
            margin-left: 600px;
            width: 200px;
            height: 180px;
            text-align: center;
            line-height: 180px;
            background-color: pink;
        }

        span {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            display: none;
        }

        .w {
            width: 1200px;
            font-weight: 700;
            color: #CCCCCC;
            margin: 20px auto;
            text-align: center;
        }

        .header {
            height: 120px;
            line-height: 120px;

            background-color: blueviolet;
        }

        .banner {
            height: 400px;
            line-height: 400px;
            background-color: red;
        }

        .main {
            height: 1000px;
            line-height: 600px;
            background-color: #008000;
        }
    </style>
</head>

<body>
<div class="slider-bar">
    <span class="goBack">返回顶部</span>
</div>
<div class="header w"></div>
<div class="banner w"></div>
<div class="main w"></div>
</body>
<script>
    //获取元素
    let slider_bar = document.querySelector('.slider-bar');
    let goBack = document.querySelector('.goBack');
    let header = document.querySelector('.header');
    let banner = document.querySelector('.banner');
    let main = document.querySelector('.main');
    let bannerTop = banner.offsetTop;
    let sliderTop = slider_bar.offsetTop - banner.offsetTop;
    let mainTop = main.offsetTop;

    //滚动至bannerTop slider_bar的绝对定位改为固定定位  slider_bar的top值为sliderTop;
    document.addEventListener("scroll", function (){
        if(window.pageYOffset>=bannerTop){
            slider_bar.style.position ='fixed';
            slider_bar.style.top =sliderTop+'px'
        }else {
            slider_bar.style.position ='absolute';
            slider_bar.style.top =300+'px'
        }

        if(window.pageYOffset>=mainTop){
            goBack.style.display = 'block'
        }else {
            goBack.style.display = 'none'
        }

    })

    slider_bar.addEventListener('click',function () {

        animate(window,0)
    })

    function  animate(obj,target,callback) {
        clearInterval(obj.timer)
        obj.timer = setInterval(function (){
            //步长值需要取整 如果是正值 则往大取整 如果是负值 则往小取整
            var step = (target - window.pageYOffset) /10;
            step = step>0?Math.ceil(step):Math.floor(step)
            if(window.pageYOffset == target){
                clearInterval(obj.timer)
            };
            //回调函数写在定时器结束的位置上
            callback&&callback()
            window.scroll(0,window.pageYOffset+step)
        },15)
    }


</script>

</html>


在这里插入图片描述

animate动画函数之筋斗云案例

animate.js

function animate(obj, target, callback) {
    // console.log(callback);  callback = function() {}  调用的时候 callback()

    // 先清除以前的定时器,只保留当前的一个定时器执行
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        // 步长值写到定时器的里面
        // 把我们步长值改为整数 不要出现小数的问题
        // var step = Math.ceil((target - obj.offsetLeft) / 10);
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            // 停止动画 本质是停止定时器
            clearInterval(obj.timer);
            // 回调函数写到定时器结束里面
            // if (callback) {
            //     // 调用函数
            //     callback();
            // }
            callback && callback();
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';

    }, 15);
}


主文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>animate函数之筋斗云</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul,li {
            list-style: none;
        }
        a {
            color: #0f0f0f;
            text-decoration: none;
        }
        body {
            background-color: #000000;
        }
        .c_nav {
            position: relative;
            width: 900px;
            height: 40px;
            margin: 200px auto;
            background:#fff url("./image/rss.png") no-repeat scroll center right;
        }
        ul {
            position: absolute;
        }
        li {
            float: left;
            width: 84px;
            height: 42px;
            text-align: center;
            line-height: 42px;
        }
        .cloud {
            position: absolute;
            width: 83px;
            height: 42px;
            top: 0;
            left: 0;
            background: url("./image/cloud.gif") no-repeat;
        }
    </style>
</head>
<script src="animate.js"></script>
<body>
    <div id="c_nav" class="c_nav">
        <span class="cloud"></span>
        <ul>
        <li><a href="javascript:;">首页新闻</a></li>
        <li><a href="javascript:;">师资力量</a></li>
        <li><a href="javascript:;">活动策划</a></li>
        <li><a href="javascript:;">企业文化</a></li>
        <li><a href="javascript:;">招聘信息</a></li>
        <li><a href="javascript:;">公司简介</a></li>
        </ul>
    </div>
    <script>
        //获取元素
        let c_nav = document.querySelector('.c_nav');
        let cloud = document.querySelector('.cloud');
        let lis = document.querySelectorAll('li');

    //   鼠标经过li时  把当前的li坐标赋值给cloud   鼠标离开li时  clod的坐标为0  鼠标点击li时 将当前li的坐标赋值给current
        current = 0;
        for(let i=0;i<lis.length;i++){
            lis[i].addEventListener('mouseenter',function () {
                animate(cloud,this.offsetLeft)
            });
            lis[i].addEventListener('mouseleave',function () {
                animate(cloud,current)
            });
            lis[i].addEventListener('click',function () {
                current = this.offsetLeft;
            })

        }

    </script>
</body>
</html>

在这里插入图片描述

移动端

移动端之触屏事件

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>移动端触屏事件</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            width: 200px;
            height: 200px;
            background-color:red;
            margin: 20px auto;
        }
    </style>
</head>
<body>
    <div class="box"></div>
</body>
<script>
    let box = document.querySelector('.box')
    box.addEventListener('touchstart',function () {
        console.log('touchstart')
    })
    box.addEventListener('touchmove',function () {
        console.log('touchmove')
    })
    box.addEventListener('touchend',function () {
        console.log('touchend')
    })
</script>
</html>

在这里插入图片描述

移动端之触屏事件对象

touchstar touchmove touchend三个事件都会有自己的事件对象

在这里插入图片描述
平时都是给元素注册触摸事件 所以重点记住targetTouches

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>移动端触摸事件对象</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            width: 200px;
            height: 200px;
            margin: 200px auto;
            background-color: red;
        }
    </style>
</head>
<body>
    <div class="box"></div>
</body>
<script>
    let box = document.querySelector('.box');
    box.addEventListener('touchstart',function (e) {
        console.log(e);
        console.log(e.touches[0])
    })
    box.addEventListener('touchend',function (e) {
        console.log(e)
    })
</script>
</html>

在这里插入图片描述

移动端之拖动元素

在这里插入图片描述

注意:手指移动也会触发滚动屏幕 所以阻止默认的屏幕滚动 e.preventDefault()


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>移动端拖动元素</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .box {
            position: absolute;
            top: 0;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: red;
        }
    </style>
</head>

<body>
<div class="box"></div>
</body>
<script>
    let box = document.querySelector('.box');
    //获取盒子原来的位置
    let x = 0;
    let y = 0;
    //获取手指的初始位置
    let starX = 0;
    let starY =0;

    box.addEventListener('touchstart',function(e){
        //获取手指初始的坐标
        starX = e.targetTouches[0].pageX;
        starY = e.targetTouches[0].pageY;
        x  = this.offsetLeft;
        y = this.offsetTop;
    })

    box.addEventListener('touchmove',function (e){
        //获取移动的坐标
        let moveX = e.targetTouches[0].pageX -starX;
        let moveY = e.targetTouches[0].pageY -starY;
        //进行赋值
        this.style.left = x +moveX+'px'
        this.style.top = y+moveY+'px';
        e.preventDefault()
    })
</script>
</html>

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值