Web API (6)

Slow animation

Principle of slow animation

Slow animation is to make the movement speed of the element change, the most common slow animation is to stop the animation speed slowly

Core idea

  • Slowly reduce the distance the box moves each time, and the speed will gradually decrease
  • Core algorithm: (target value-current position)/10 as the distance step of each movement
  • Stop condition: Let the current position of the box equal to the target position, then stop the timer
  • Note that the step value needs to be rounded

<!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;
        }
        
        button {
            margin: 50px;
        }
        
        img {
            position: absolute;
            display: block;
            width: 200px;
            height: 200px;
            border-radius: 50%;
        }
    </style>
</head>

<body>
    <img src="./image/picture.jpg" alt="" class="img">
    <button>点击移动至800</button>
    <button>点击移动至0</button>
    
    <script>
        var bth = document.querySelectorAll('button');
        var img = document.querySelector('img')
            // obj:目标对象   target:目标位置
        function aniamte(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() {
            aniamte(img, 800)
        })
        bth[1].addEventListener('click', function() {
            aniamte(img, 0)
        })
    </script>
</body>

</html>


Insert picture description here

Add callback function for slow animation

Core idea: The callback function should be added to the end of the timer

<!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;
        }
        
        button {
            margin: 50px;
        }
        
        img {
            position: absolute;
            display: block;
            width: 200px;
            height: 200px;
            border-radius: 50%;
        }
        
        .photo {
            width: 500px;
            height: 500px;
        }
    </style>
</head>

<body>
    <button>点击移动至800</button>
    <button>点击移动至0</button>
    <img src="./image/picture.jpg" alt="" class="img">
    <script>
        var bth = document.querySelectorAll('button');
        var img = document.querySelector('img')
            // obj:目标对象   target:目标位置
        function aniamte(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() {
            aniamte(img, 800, function() {
                img.className = 'img'
            })
        })
        bth[1].addEventListener('click', function() {
            aniamte(img, 0, function() {
                img.className = 'photo img'

            })
        })
    </script>
</body>

</html>

Insert picture description here

animate animation function

animate.js file


var bth = document.querySelectorAll('button');
var img = document.querySelector('img')
    // obj:目标对象   target:目标位置
function aniamte(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() {
    aniamte(img, 800, function() {
        img.className = 'img'
    })
})
bth[1].addEventListener('click', function() {
    aniamte(img, 0, function() {
        img.className = 'photo img'

    })
})

Master file

<!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>
        .sliderbar {
            position: fixed;
            right: 0;
            bottom: 100px;
            width: 40px;
            height: 40px;
            text-align: center;
            line-height: 40px;
            color: #fff;
            cursor: pointer;
        }
        
        .con {
            position: absolute;
            top: 0;
            left: 0;
            width: 200px;
            height: 40px;
            background-color: purple;
            z-index: -1;
        }
    </style>
    <script src="./animate.js"></script>
</head>

<body>
    <div class="sliderbar">
        <span> ← </span>
        <div class="con">问题反馈</div>
    </div>

    <script>
        var sliderbar = document.querySelector('.sliderbar');
        var con = document.querySelector('.con');

        sliderbar.addEventListener('mouseenter', function() {
            aniamte(con, -160, function() {
                sliderbar.children[0].innerHTML = "→"
            })
        })


        sliderbar.addEventListener('mouseleave', function() {
            aniamte(con, 0, function() {
                sliderbar.children[0].innerHTML = "← "
            })
        })
    </script>

</body>

</html>

Insert picture description here

Carousel

The carousel picture is also called the focus picture, which is a common webpage special effect in the webpage.

Functional Requirements:

1. The mouse passes over the carousel diagram module, the left and right buttons are displayed, and when left, the left and right buttons are hidden.

2. Click the right button once, the picture will be played to the left, and so on, the left button is the same.

3. While the picture is playing, the small circle module below changes along with it.

4. Click the small circle to play the corresponding picture.

5. If the mouse does not pass the carousel picture, the carousel picture will automatically play the picture.

6. Mouse over, carousel picture module, auto play stop

animate.js

function aniamte(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);

}


Master file

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>轮播图</title>
        <style>
            * {
            margin: 0;
            padding: 0;
        }
        
        ul,
        ol {
            list-style: none;
        }
        
        .foucs {
            overflow: hidden;
            position: relative;
            width: 990px;
            height: 540px;
            margin: 200px auto;
        }
        
        a {
            display: none;
            position: absolute;
            width: 40px;
            height: 40px;
            color: white;
            top: 50%;
            transform: translateY(-50%);
            text-decoration: none;
            text-align: center;
            line-height: 40px;
            font-size: 20px;
            background-color: rgba(0, 0, 0, 0.5);
        }
        
        .arrow-l {
            left: 0;
            border-radius: 0px 20px 20px 0px;
        }
        
        .arrow-r {
            right: 0;
            border-radius: 20px 0px 0px 20px;
        }
        
        .Picture {
            /* 注意 ul移动 所以必须要加定位 */
            position: absolute;
            top: 0;
            left: 0;
            width: 600%;
            z-index: -1;
        }
        
        .Picture li {
            float: left;
        }
        
        .Picture li img {
            width: 990px;
            height: 540px;
        }
        
        .circle {
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            bottom: 20px;
            height: 40px;
            border-radius: 20px;
            background-color: rgba(0, 0, 0, 0.5);
        }
        
        .circle li {
            float: left;
            width: 10px;
            height: 10px;
            margin: 15px;
            background-color: white;
            border-radius: 50%;
        }
        
        .circle .curent {
            background-color: red;
        }
    </style>
    </head>
    <script type="text/javascript" src="./animate.js">
    </script>

    <body>
        <div class="foucs">
            <!-- 左右箭头 -->
            <a href="javascript:;" class="arrow-l">
                <</a> <a href="javascript:;" class="arrow-r"> >
            </a>

            <!-- 图片容器 -->
            <ul class="Picture">
                <li><img src="./image/focus1.jpg" alt=""></li>
                <li><img src="./image/focus2.jpg" alt=""></li>
                <li><img src="./image/focus3.jpg" alt=""></li>
                <li><img src="./image/focus4.jpg" alt=""></li>

            </ul>
            <!-- 底部导航 -->
            <ol class="circle">

            </ol>
        </div>

        <script>
            // 1.获取元素
            var focus = document.querySelector(".foucs")
            var arrow_l = document.querySelector('.arrow-l');
            var arrow_r = document.querySelector('.arrow-r');
            /*获取ul的宽度*/
            var fousWidth = focus.offsetWidth;
            console.log(fousWidth)

            var ul = document.querySelector('.Picture');
            var ol = document.querySelector('.circle');
            // 克隆第一张照片



            //2.绑定事件  鼠标经过轮播图模块的时候 左右箭头会显示  鼠标离开轮播图的时候  左右箭头会消失
            focus.addEventListener('mouseenter', function() {
                arrow_l.style.display = 'block';
                arrow_r.style.display = 'block';
                clearInterval(timer)
            })

            focus.addEventListener('mouseleave', function() {
                arrow_l.style.display = 'none';
                arrow_r.style.display = 'none';
                timer = setInterval(function(){
                    arrow_r.click()
                },2000)
            })

            //3.动态创建小圆圈 有几张图片就想对应的创建几个小圆圈
            for (var i = 0; i < ul.children.length; i++) {
                // 创建li
                var li = document.createElement('li');
                // 为li设置自定义属性
                li.setAttribute('index', i)
                // 追加到ul里面
                ol.append(li);

                //4.点击当前的小圆圈,给当前的小圆圈添加类,同时使用排他思想清除其它li的样式
                li.addEventListener('click', function() {
                    for (var i = 0; i < ol.children.length; i++) {
                        ol.children[i].className = ''
                    };
                    this.className = 'curent';
                    /* 5.为li设置自定义属性,点击小圆圈,ul的移动距离是索引号乘以容器的宽度 注意为负值*/
                    var index = this.getAttribute('index');
                    /*把index的值赋值给circle及num 以保持播放图片时图片和小圆圈能保持同步*/
                    num = index;
                    circle = index;
                    aniamte(ul, -index * fousWidth)
                })

            }
            //6.点击右侧按钮  图片滚动一张 利用无缝滚动要克隆第一张图片,追加到ul后面,进行判断  注意声明一个变量num实现自增效果
            var first = ul.children[0].cloneNode(true);
            ul.append(first);
            var num = 0;
            var circle = 0;
            // 开启节流阀
            var flag = true;
            arrow_r.addEventListener('click', function() {
        
                if(flag){
                    flag = false;
                    if (num == ul.children.length - 1) {
                            ul.style.left = 0;
                            num = 0
                        }
                        num++;
                    
                        aniamte(ul, -num * fousWidth, function(){
                            flag  = true;
                            });
                        // 7.点击右侧按钮,小圆圈跟随一起变化,声明一个变量circle来控制小圆圈的播放
                        circle++;
                        if (circle == ol.children.length) {
                            circle = 0;
                        }
                        for (var i = 0; i < ol.children.length; i++) {
                            ol.children[i].className = ''
                        }
                        ol.children[circle].className = 'curent'
                }
                
                
                })
            
    
            //左侧按钮做法
            arrow_l.addEventListener('click', function() {
                if(flag) {
                    // 关闭节流阀
                    flag = false;
                    if (num == 0) {
                        num= ul.children.length-1;
                        ul.style.left = -num * fousWidth +"px"
                        
                    }
                    num--;
                    
                    aniamte(ul, -num * fousWidth,function(){
                        // 开启节流阀
                        flag = true;
                        });
                    // 7.点击右侧按钮,小圆圈跟随一起变化,声明一个变量circle来控制小圆圈的播放
                    circle--;
                    // 如果circle<0,则代表目前处于第一张图片 ,则小圆圈的索引为3 
                    if (circle <0 ) {
                        circle = ol.children.length-1;
                    }
                    for (var i = 0; i < ol.children.length; i++) {
                        ol.children[i].className = ''
                    }
                    ol.children[circle].className = 'curent'
                    
                    
                }
                
            })
            
            // 8.开启自动播放功能
            var timer = setInterval(function(){
                arrow_r.click()
            },2000)
            // 将ol里面的第一个li设置为红色 也就是添加.curent类名
            ol.children[0].className = 'curent'
        </script>


</html>


Insert picture description here

Throttle valve

Prevent the continuous click of the carousel button from causing excessively fast playback.

The purpose of the throttle: When the content of the previous function animation is executed, the next function animation is executed, so that the event cannot be triggered continuously.

Core realization idea: use callback function, add a variable to control, lock function and unlock function.

aniamte animation function back to top

Scroll the window to any position on the page 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;
            background-color: blueviolet;
        }
        
        .banner {
            height: 400px;
            background-color: red;
        }
        
        .main {
            height: 2000px;
            background-color: #008000;
        }
    </style>
</head>

<body>
    <div class="slider-bar">
        <span class="goBack">返回顶部</span>
    </div>
    <div class="header w">header</div>
    <div class="banner w">banner</div>
    <div class="main w">主体</div>
</body>
<script>
    //获取元素
    var slider = document.querySelector('.slider-bar');
    var goBack = document.querySelector('.goBack');
    var header = document.querySelector('.header');
    var banner = document.querySelector('.banner');
    var main = document.querySelector('.main');
    //bannerTop就是被卷去头部的大小,一定要写到滚动的外面 mainTop同理
    var mainTop = main.offsetTop;
    var bannerTop = banner.offsetTop;
    var sliderbarTop = slider.offsetTop - bannerTop;
    // 绑定scroll事件
    document.addEventListener('scroll', function() {
        if (window.pageYOffset >= bannerTop) {
            slider.style.position = 'fixed'
            slider.style.top = sliderbarTop + "px"

        } else {
            slider.style.position = 'absolute';
            slider.style.top = "300px"

        }

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

        } else {
            goBack.style.display = 'none'
        }
    })

    //当我们点击返回顶部模块,就让窗口滚动至页面的最顶部
    goBack.addEventListener('click', function() {
        animate(window, 0)
    })


    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 - window.pageYOffset) / 10;
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            if (window.pageYOffset == target) {
                // 停止动画 本质是停止定时器
                clearInterval(obj.timer);
                // 回调函数写到定时器结束里面
                // if (callback) {
                //     // 调用函数
                //     callback();
                // }
                callback && callback();
            }
            // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
            // obj.style.left = window.pageYOffset + step + 'px';
            window.scroll(0, window.pageYOffset + step);
        }, 15);
    }
</script>

</html>


Insert picture description here

Somersault cloud case of animate function

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);
}


Master file


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>筋斗云案例</title>
        <script src="animate.js"></script>
    </head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul {
            list-style: none;

        }

        body {
            background-color: black;
        }

        .c-nav {
            position: relative;
            width: 900px;
            height: 42px;
            background: #fff url(image/rss.png) no-repeat right center;
            margin: 100px auto;
        }

        .c-nav ul {
            position: absolute;
        }

        .c-nav li {
            float: left;
            width: 83px;
            text-align: center;
            line-height: 42px;
        }

        .c-nav li a {
            color: #333;
            text-decoration: none;
            display: inline-block;
            height: 42px;
        }

        .c-nav li a:hover {
            color: white;
        }


        .cloud {
            position: absolute;
            left: 0;
            top: 0;
            width: 83px;
            height: 42px;
            background: url(image/cloud.gif) no-repeat;
        }
    </style>
    <body>
        <div id="c_nav" class="c-nav">
            <span class="cloud"></span>
            <ul>
                <li class="current"><a href="#">首页新闻</a></li>
                <li><a href="#">师资力量</a></li>
                <li><a href="#">活动策划</a></li>
                <li><a href="#">企业文化</a></li>
                <li><a href="#">招聘信息</a></li>
                <li><a href="#">公司简介</a></li>
                <li><a href="#">我是佩奇</a></li>
                <li><a href="#">啥是佩奇</a></li>
            </ul>
        </div>
    </body>
    <script>
        //获取事件源
        var c_nav = document.querySelector('#c_nav');
        var cloud = document.querySelector('.cloud');
        var lis = c_nav.querySelectorAll('li');
        console.log(lis)

        //声明current变量作为筋斗云的起始位置
        var current = 0;
        // 给每个li绑定事件
        for (var i = 0; i < lis.length; i++) {
            // 鼠标经过的时候
            lis[i].addEventListener('mouseenter', function() {
                aniamte(cloud, this.offsetLeft)
            })

            // 鼠标离开的时候
            lis[i].addEventListener('mouseleave', function() {
                aniamte(cloud, current)
            })


            // 鼠标点击的时候
            lis[i].addEventListener('click', function() {
                current = this.offsetLeft;
            })

        }
    </script>
</html>

Insert picture description here

Mobile

Touch screen events on mobile

Insert picture description here


<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title>移动端触摸事件</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }

            .box {
                width: 200px;
                height: 200px;
                background-color: red;
            }
        </style>
    </head>

    <body>
        <div class="box"></div>
        <script>
            var box = document.querySelector('.box');
            box.addEventListener('touchstart', function() {
                console.log('touchstar')
            })
            box.addEventListener('touchmove', function() {
                console.log('touchmove')
            })
            box.addEventListener('touchend', function() {
                console.log('touchend')
            })
        </script>
    </body>

</html>

Insert picture description here

Touch screen event object on mobile

touchstar touchmove touchend three events will have their own event object

Insert picture description here
Usually register touch events for elements, so focus on targetTouches

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title>移动端触摸事件</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }

            .box {
                width: 200px;
                height: 200px;
                background-color: red;
            }
        </style>
    </head>

    <body>
        <div class="box"></div>
        <script>
            var box = document.querySelector('.box');
            box.addEventListener('touchstart', function(e) {
                console.log(e.targetTouches[0]);
                
            })
            
        </script>
    </body>

</html>



Insert picture description here

Drag element on mobile

(1) Touch element touchstar: Get the initial coordinates of the finger. At the same time get the original position of the box
(2) Move event touchmove: get the sliding distance of the finger, and move the box

Note: Finger movement will also trigger the scrolling of the screen, so prevent the default screen scrolling e.preventDefault()


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            position: absolute;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div></div>
    <script>
        
        var div = document.querySelector('div');
        var startX = 0; //获取手指初始坐标
        var startY = 0;
        var x = 0; //获得盒子原来的位置
        var y = 0;
        div.addEventListener('touchstart', function(e) {
            //  获取手指初始坐标
            startX = e.targetTouches[0].pageX;
            startY = e.targetTouches[0].pageY;
            x = this.offsetLeft;
            y = this.offsetTop;
        });

        div.addEventListener('touchmove', function(e) {
            //  计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标
            var moveX = e.targetTouches[0].pageX - startX;
            var moveY = e.targetTouches[0].pageY - startY;
            // 移动我们的盒子 盒子原来的位置 + 手指移动的距离
            this.style.left = x + moveX + 'px';
            this.style.top = y + moveY + 'px';
            e.preventDefault(); // 阻止屏幕滚动的默认行为
        });
    </script>
</body>

</html>

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_45419127/article/details/112225626