筋斗云效果案例(JS)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0; padding: 0;}
        ul {list-style:none;}
        body {
            background-color: #000;
        }
        .nav {
            width: 800px;
            height: 42px;
            background: #fff;
            margin: 100px auto;
            border-radius: 5px;
            position: relative; 
        }
        .cloud {
            width: 83px;
            height: 42px;
            position: absolute;
            top: 0;
            left: 0;
            background: url(cloud.gif) no-repeat;
        }
        .nav ul {
            position: absolute;
            top: 0;
            left: 0;
        }
        .nav li {
            float: left;
            width: 88px;
            height: 42px;
            line-height: 42px;
            text-align: center;
            color: #000;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="nav" id="nav">
        <span class="cloud" id="cloud"></span>
        <ul id="box">
            <li>首页新闻</li>
            <li>千锋师资</li>
            <li>千锋活动策划</li>
            <li>企业文化</li>
            <li>招聘信息</li>
            <li>公司简介</li>
            <li>上海校区</li>
            <li>广州校区</li>
        </ul>
    </div>
    <script>
        var cloud = document.querySelector('#cloud')
        var list = document.querySelectorAll('#box li') // list是一个伪数组
        // 循环遍历list,但是普通for拿不到li的下标
        // Array.from() 可以将类数组对象转换成数组
        var arrList = Array.from(list)
        console.log(list)
        console.log(arrList)
        var i = 0 // 默认云的位置在第0个
        arrList.forEach((li, index) => {
            // forEach每循环一次都是一个函数,每个函数里都有一个自己的index,所以可以直接使用
            // var变量或者函数参数之于函数相当于let变量之于块级
            li.onmouseenter = function () {
                console.log(index)
                // 让这朵云运动到当前li的坐标位置
                move1(cloud, 'left', this.offsetLeft) // offsetLeft相对于父级元素的坐标
            }

            li.onclick = function(){
                // 这里没有云的移动,这里只是负责记录点击的位置也就是下标
                // 记录云所要回到的位置
                i = index
            }

            li.onmouseleave = function (){
                // 让cloud回到上一次点击的位置,按照click里面记录的下标来移动
                move1(cloud, 'left', arrList[i].offsetLeft)
            }
        })
        
		/**
     * 封装一个缓冲运动,咱们的缓冲算法里速度跟时间没有关系的,所以这里不需要传时间,时间就是根据距离来自动得到的
     * @param ele     要运动的元素对象
     * @param attr       运动的属性名
     * @param end        运动的终点,单位px
     * @param fn       回调函数,在运动结束以后执行的函数 
     */
    move1: function(ele, attr, end, fn) {
      // 开启定时器之前把旧的先清除掉
      clearInterval(ele.timer)
      var start = parseInt(this.getStyle(ele, attr)) // getStyle(ele,attr)获取ele元素的位置
      ele.timer = setInterval(function(){
        // 计算剩下距离
        var distance = parseInt(end) - start
        // 计算当前这一步的速度,是剩下距离的十分之一
        // speed就是当前这一步要往前走的距离
        // 如果运动是负方向,distance小于0,speed也小于0,剩下最后几步负零点几的时候如果向上取整直接就得到0了,就不能运动到终点了
        var speed = distance > 0 ? Math.ceil(distance / 10) : Math.floor(distance / 10)
        // start得往前加上这一步要走的距离
        start += speed 
        // 把更新之后的start赋值给属性
        ele.style[attr] = start + 'px'
        // 判断终点
        // 由于缓冲运动最后是一像素一像素运动的,所以他一定能刚好达到终点
        if(start === end){
          clearInterval(ele.timer)
          fn && fn()
        }

      },30)
    }
    </script>
</body>
</html>

你可能感兴趣的:(筋斗云效果案例(JS))