Web API(6)

遅いアニメーション

スローアニメーションの原理

遅いアニメーションは要素の移動速度を変更することです。最も一般的な遅いアニメーションはアニメーション速度をゆっくり停止することです

コアアイデア

  • ボックスが移動するたびにゆっくりと距離を減らし、速度を徐々に下げていきます
  • コアアルゴリズム:(目標値-現在の位置)/ 10各移動の距離ステップとして
  • 停止条件:ボックスの現在位置を目標位置と等しくしてから、タイマーを停止します。
  • ステップ値は丸める必要があることに注意してください

<!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>


ここに画像の説明を挿入

遅いアニメーションのコールバック関数を追加

コアアイデア:コールバック関数をタイマーの最後に追加する必要があります

<!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>

ここに画像の説明を挿入

アニメーション機能のアニメーション化

animate.jsファイル


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'

    })
})

マスターファイル

<!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>

ここに画像の説明を挿入

カルーセル

カルーセル画像はフォーカス画像とも呼ばれ、Webページで一般的なWebページの特殊効果です。

機能要件:

1.マウスがカルーセルダイアグラムモジュール上を通過すると、左ボタンと右ボタンが表示され、左の場合は左ボタンと右ボタンが非表示になります。

2.右ボタンを1回クリックすると、画像が左に再生されます。以下同様に、左ボタンも同じです。

3.画像の再生中に、下の小さな円モジュールがそれに伴って変化します。

4.小さな円をクリックして、対応する画像を再生します。

5.マウスがカルーセル画像を通過しない場合、カルーセル画像は自動的に画像を再生します。

6.マウスオーバー、カルーセル画像モジュール、自動再生停止

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

}


マスターファイル

<!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>


ここに画像の説明を挿入

スロットルバルブ

カルーセルボタンを連続してクリックしても、再生が速くなりすぎないようにします。

スロットルの目的:前の機能アニメーションの内容を実行すると、次の機能アニメーションが実行されるため、イベントを継続的にトリガーすることはできません。

コア実現のアイデア:コールバック関数を使用し、制御する変数を追加し、関数をロックし、関数のロックを解除します。

アニアムテアニメーション機能トップに戻る

ウィンドウをページウィンドウ上の任意の位置にスクロールします。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>


ここに画像の説明を挿入

アニメーション機能の宙返りクラウドケース

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>
    <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>

ここに画像の説明を挿入

モバイル

モバイルでのタッチスクリーンイベント

ここに画像の説明を挿入


<!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>

ここに画像の説明を挿入

モバイル上のタッチスクリーンイベントオブジェクト

touchstar touchmove touchend3つのイベントには独自のイベントオブジェクトがあります

ここに画像の説明を挿入
通常、要素のタッチイベントを登録するため、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>



ここに画像の説明を挿入

モバイルで要素をドラッグ

(1)タッチ要素touchstar:指の初期座標を取得します。同時にボックスの元の位置を取得します
(2)移動イベントtouchmove:指のスライド距離を取得し、ボックスを移動します

注:指を動かすと画面のスクロールもトリガーされるため、デフォルトの画面スクロールを防止します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>

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_45419127/article/details/112225626
おすすめ