webApi06


小概

本章的学习内容:原生js写轮播图(匀速动画应用),缓动动画的封装和使用,导航栏筋斗云案例(缓动动画应用)


提示:以下是本篇文章正文内容,下面案例可供参考

1. 轮播图案例(淘宝滚动型)

  • 轮播图的应用基本在每个电商网站上都可以看见,应用场景非常广泛。下面我们用原生js实现轮播图的制作
  • 图片轮播的原理就是使用上一章我们封装的匀速动画实现的:在css样式中,把所有需要展示的图片连接成一张长图,为父盒子设置overflow: hidden(溢出裁剪), 通过匀速动画修改该图片的letf值达到展示不同图片的效果 下面是css样式
    <style type="text/css">
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            border: 0;
        }

        .all {
            width: 500px;
            height: 200px;
            padding: 7px;
            border: 1px solid #ccc;
            margin: 100px auto;
            position: relative;
        }

        .screen {
            width: 500px;
            height: 200px;
            overflow: hidden;
            position: relative;
        }

        .screen li {
            width: 500px;
            height: 200px;
            overflow: hidden;
            float: left;
        }

        .screen ul {
            position: absolute;
            left: 0;
            top: 0px;
            width: 3000px;
        }

        .all ol {
            position: absolute;
            right: 10px;
            bottom: 10px;
            line-height: 20px;
            text-align: center;
        }

        .all ol li {
            float: left;
            width: 20px;
            height: 20px;
            background: #fff;
            border: 1px solid #ccc;
            margin-left: 10px;
            cursor: pointer;
        }

        .all ol li.current {
            background: yellow;
        }

        #arr {
            display: none;
        }

        #arr span {
            width: 40px;
            height: 40px;
            position: absolute;
            left: 5px;
            top: 50%;
            margin-top: -20px;
            background: #000;
            cursor: pointer;
            line-height: 40px;
            text-align: center;
            font-weight: bold;
            font-family: '黑体';
            font-size: 30px;
            color: #fff;
            opacity: 0.3;
            border: 1px solid #fff;
        }

        #arr #right {
            right: 5px;
            left: auto;
        }
    </style>
</head>

<body>
    <div class="all" id='box'>
        <div class="screen">
            <ul>
                <li><img src="images/01.jpg" width="500" height="200" /></li>
                <li><img src="images/02.jpg" width="500" height="200" /></li>
                <li><img src="images/03.jpg" width="500" height="200" /></li>
                <li><img src="images/04.jpg" width="500" height="200" /></li>
                <li><img src="images/05.jpg" width="500" height="200" /></li>
                <li><img src="images/01.jpg" width="500" height="200" /></li>
            </ul>
            <ol>
                <li class="current">1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
                <li>5</li>
            </ol>
        </div>
        <div id="arr">
            <span id="left">&lt;</span>
            <span id="right">&gt;</span>
        </div>
    </div>

1.2 需求分析

1.鼠标移入移出box:显示/隐藏arr箭头盒子
2.鼠标单击上一页/下一页:滚动到对应下标的图片
* 注意点:实现无限循环
3.鼠标单击页码:滚动到对应下标的图片
4.自动轮播:定时器实现

需要用到上期的匀速动画封装函数

/**
* @description:匀速动画
* @param {number}target : 目标位置 
* @param {dom}ele : 目标元素 
* @return: 
*/
function animationMove(target, ele) {
    //1.开始动画之前先清除之前的定时器,以本次移动为准
    clearInterval(ele.timeID);
    //2.开始本次动画
    ele.timeID = setInterval(function () {
        //2.1 获取元素当前位置
        let currentLeft = ele.offsetLeft;
        /* 使用布尔类型存储移动方向 true:从左往右  false:从右往左*/
        let isLeft = target >= currentLeft ? true : false;
        //2.2 开始移动
        isLeft ? currentLeft += 10 : currentLeft -= 10;
        ele.style.left = currentLeft + 'px';
        //2.3 边界检测
        /* 
        这个语法是一个比较表达式,比较两边式子结果是否一致
            左边: isLeft 布尔类型 true:从左往右  false:从右往左
            右边: currentLeft >= target 结果布尔类型
                (1)当isLeft为true(从左往右),只有当右边式子也为true才会成立
                (2)当isLeft为false(从右往左),只有当右边式子也为false才会成立。此时只有当currentLeft < target的时候右边式子才是false
         */
        if (isLeft == currentLeft >= target) {
            //停止动画
            clearInterval(ele.timeID);
            //元素复位
            ele.style.left = target + 'px';
        };
    }, 20);
};

1.3 功能1 功能2

1.鼠标移入移出box:显示/隐藏arr箭头盒子
2.鼠标单击上一页/下一页:滚动到对应下标的图片

        // 1. 获取页面元素
        let box = document.querySelector('#box'); // 父盒子
        let screen = document.querySelector('.screen'); // 轮播图展现父盒子
        let ul = screen.children[0];//图片列表
        let ol = screen.children[1];//页码列表
        let arr = document.querySelector('#arr');//arrow箭头盒子
        let left = arr.children[0];//上一页
        let right = arr.children[1];//上一页

		//声明一个全局变量:存储当前的图片下标
        let index = 0;

        //2.注册事件
        //2.1 鼠标移入box
        box.onmouseover = function () {
            //3.事件处理:显示箭头arr盒子
            arr.style.display = 'block';
        };

        //2.2 鼠标移出box
        box.onmouseout = function () {
            //3.事件处理:隐藏箭头arr盒子
            arr.style.display = 'none';
        };

        //2.3 点击下一页
        right.onclick = function () {
            //3. 事件处理:滚动到对应下标的图片 index++
            // 3.1 计算对应下标
            if (index == ul.children.length - 1) {
                index = 0;
            } else {
                index++;
            }
            console.log(index);
            // 3.2 开始滚动
            animationMove(-index * screen.offsetWidth, ul);
            // 3.3 排他思想修改页码样式
            for (let i = 0; i < ol.children.length; i++) {
                if (i == index) {
                    ol.children[i].className = 'current';
                } else {
                    ol.children[i].className = '';
                }
            }
        };

        //2.4 点击上一页
        left.onclick = function () {
            //3. 事件处理:滚动到对应下标的图片 index--
            // 3.1 计算对应下标
            if (index == 0) {
                index = 4;
            } else {
                index--;
            }
            console.log(index);
            // 3.2 开始滚动
            animationMove(-index * screen.offsetWidth, ul);
            // 3.3 排他思想修改页码样式
            for (let i = 0; i < ol.children.length; i++) {
                if (i == index) {
                    ol.children[i].className = 'current';
                } else {
                    ol.children[i].className = '';
                }
            }
        };

1.4 实现循环轮播

其实上已经实现了无限轮播,但是出现了一个问题,第5张下一张到第一张的时候,切换方式是直接左移到第一张,这种切换方式有问题。

解决方法:视觉欺骗
将第一张图片复制到最后一张图片的后面,实际上就有6张图片了,只不过第一张与最后一张是同一张,判断下标为5时,index=0 ;ul.style.left = -index*(照片宽度),相当于第六张切到第一张的时候 瞬间切换到第一张, 然后展示第一张切换第二张的动画。

还会出现一个问题,就是页码(0 1 2 3 4)与图片的下标不对应(0 1 2 3 4 5);
解决方法:判断当图片[[5]时,给页码[0]设置样式、

        //2.3 点击下一页
        right.onclick = function () {
            //3. 事件处理:滚动到对应下标的图片 index++
            // 3.1 计算对应下标
            if (index == ul.children.length - 1) {
                index = 0;
                ul.style.left = -index*screen.offsetWidth + 'px';        // 重点:轮播图无限轮播的秘密,视觉欺骗
            }
            index++;
            console.log(index);
            // 3.2 开始滚动
            animationMove(-index * screen.offsetWidth, ul);
            // 3.3 排他思想修改页码样式
            for (let i = 0; i < ol.children.length; i++) {
                if (i == index ) {
                    ol.children[i].className = 'current';
                } else {
                    ol.children[i].className = '';
                }
            }
            if(index == ul.children.length-1){
                ol.firstElementChild.className = 'current';
            }
        };
        //2.4 点击上一页
        left.onclick = function () {
            //3. 事件处理:滚动到对应下标的图片 index--
            // 3.1 计算对应下标
            if (index == 0) {
                index = ul.children.length-1;
                ul.style.left = -index*screen.offsetWidth +'px';
            }
            index--;
            console.log(index);
            // 3.2 开始滚动
            animationMove(-index * screen.offsetWidth, ul);
            // 3.3 排他思想修改页码样式
            for (let i = 0; i < ol.children.length; i++) {
                if (i == index) {
                    ol.children[i].className = 'current';
                } else {
                    ol.children[i].className = '';
                }
            }
        };

1.5 功能3 功能4

实现鼠标单击页码,跳到对应的图片上
实现自动轮播,鼠标移入停止轮播,离开继续轮播

        //2.5 页码点击
        for (let i = 0; i < ol.children.length; i++) {
            ol.children[i].onclick = function () {   //i =0 1 2 3 4
                //事件处理 this:当前点击的页码
                console.log(i);
                // 3.1 开始滚动
                animationMove(-i*screen.offsetWidth,ul);
                // 3.2 设置index与当前点击的页码一致
                index =i;
                // 3.3 排他思想修改样式
                for(let j=0;j<ol.children.length;j++){
                    if(i==j){
                        ol.children[j].className = 'current';
                    }else{
                        ol.children[j].className = '';
                    }
                }
            }
        }
        // 开启自动轮播
        let timeID = setInterval(function(){
                right.onclick();
            },2000);
        //2.1 鼠标移入box
        box.onmouseover = function () {
            //3.事件处理:显示箭头arr盒子
            arr.style.display = 'block';
            //清除自动轮播
            clearInterval(timeID);
        };
        //2.2 鼠标移出box
        box.onmouseout = function () {
            //3.事件处理:隐藏箭头arr盒子
            arr.style.display = 'none';
            //开启自动轮播
            timeID = setInterval(function(){
                right.onclick();
            },2000);
        };

2. 缓速动画

  1. 什么是缓动动画 : 速度由快到慢的动画
    匀速: 速度不变
    变速: 速度变化,更符合现实世界物体运动规律
    2. 缓动动画核心原理 : 本次移动距离 = (目标位置-当前位置)/10
    3. 缓动动画特点
    3.1 需要取整 : 因为缓动动画公式是除法,而除法会产生小数。 像素一般不给小数的,所以需要取整。
    3.2 没有误差 : 因为缓动动画公式计算到最后每次只移动1px
    * 不需要边界检测: current >= target , 元素复位
    * 需要终点检测 : current == target

缓速动画与匀速动画的区别,
缓速动画;每次移动的值 =(目标距离-当前距离)/10 ,不需要边界检测,移动方向不用判断(向右移动移动距离向上取整, 向左移动移动距离向下取整)
匀速动画:每次移动固定的值,需要边界检测,需要判断移动方向,需要复位、

        function animationSlow(target,ele){
            //1.先清除以前的定时器,以本次移动为准
            clearInterval(ele.timeID);
            //2.开始本次动画
            ele.timeID = setInterval(function(){
                //2.1.获取当前位置
                let currentLeft = ele.offsetLeft;
                //2.2.计算本次移动距离 = (目标位置-当前位置)/10
                let step = (target-currentLeft)/10;
                //取整 ; 正数:从左往右,向上取整  负数:从右往左,向下取整
                step =   step > 0 ? Math.ceil(step) : Math.floor(step);
                //2.3.开始移动
                currentLeft += step;
                ele.style.left = currentLeft + 'px';
                //2.4.终点检测
                if( currentLeft == target){
                    clearInterval(ele.timeID);
                };
            },20);
        };

3. 筋斗云案例

  • 缓速动画的金典案例
   <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul {
            list-style: none;
        }
        body {
            background-color: #333;
        }
        .nav {
            width: 800px;
            height: 42px;
            margin: 100px auto;
            /*background-color: red;*/
            background: #fff url(images/rss.png) no-repeat right center;
            border-radius: 10px;
            position: relative;
        }
        .nav li {
            width: 83px;
            height: 42px;
            /*background-color: red;*/
            text-align: center;
            line-height: 42px;
            float: left;
            cursor: pointer;
        }
        ul {
            position: relative;
        }
        .nav span {
            position: absolute;
            top: 0;
            left: 0;
            width: 83px;
            height: 42px;
            background: url(images/cloud.gif) no-repeat;
        }
    </style>
</head>

<body>
    <div class="nav">
        <span id="cloud"></span>
        <ul id="navBar">
            <li>首页</li>
            <li>博客</li>
            <li>程序员学院</li>
            <li>下载</li>
            <li>论坛</li>
            <li>问答</li>
            <li>代码</li>
            <li>直播</li>
        </ul>
    </div>
</body>
</html>
<script src="./animation.js"></script>   //封装了匀速和缓速的两个函数方法

<script>
    /*需求分析 
    1.鼠标移入每一个li元素: 筋斗云缓动到移入的li元素位置
    2.鼠标移出每一个li元素: 筋斗云缓动到  主人的位置
    3.鼠标单击每一个li元素: 筋斗云 主人变成单击的li元素
    */

    //1.获取元素
    let cloud = document.querySelector('#cloud');
    let liList = document.querySelectorAll('#navBar>li');
    //声明一个全局变量存储筋斗云的主人(默认第一个li元素)
    let zhuren = liList[0];


    //2.注册事件
    for(let i = 0;i<liList.length;i++){
        
        //2.1 移入
        liList[i].onmouseover = function(){
            //3.事件处理  this: 移入的li元素
            animationSlow(this.offsetLeft,cloud);
        };
        //2.2 移出
        liList[i].onmouseout = function(){
             //3.事件处理  this: 移出的li元素
             animationSlow(zhuren.offsetLeft,cloud);
        };
        //2.3 单击
        liList[i].onclick = function(){
            //3.事件处理 this: 单击的li元素
            zhuren = this;
        };
    };
</script>

总结

匀速动画和缓速动画两个知识点很重要,尤其是利用匀速动画制作轮播图和筋斗云这两个案例,非常的金典 肥常的好用。虽然现在组件很多,写项目的时候直接调用就可以,但是这并不影响我准备敲他‘10’遍的。好记性不如敲烂指头,奥力给!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值