The system takes you to learn WebAPIs - animation (6th lecture)

Web APIs

The learning objectives of this article:

Ability to encapsulate simple animation functions

Can understand the encapsulation of easing animation

Ability to use animation functions

Be able to write a case of web page carousel

Ability to write mobile touch screen events

1.1. Animation function encapsulation

1.1.1 Principle of easing effect

Easing animation is to change the speed of the movement of the element, the most common is to let the speed slowly stop

Ideas:

  1. Let the distance of the box gradually decrease each time, and the speed will slowly fall.
  2. Core algorithm: (target value - current position) / 10 as the distance step for each move
  3. The conditions for stopping are: Stop the timer when the current box position is equal to the target position
  4. Note that the step value needs to be rounded

1.1.2 Animation function moving between multiple target values

The animation function can be moved from 800 to 500.

When we click the button, determine whether the step size is positive or negative

​ 1. If it is a positive value, the step size is rounded up

​ 2. If it is a negative value, the step size is rounded up

1.1.3 Add callback function to dynamic function

The principle of callback function: function can be used as a parameter. Pass this function as a parameter to another function. When the function is executed, the function passed in is executed. This process is called callback.

The position where the callback function is written: the position where the timer ends.

1.1.4 Animation full version code:

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

1.2. Common web page special effects cases

1.2.1 Case: web page carousel

Carousel image, also known as focus image, is a relatively common web page effect in web pages.

Functional Requirements:

​ 1. When the mouse passes the carousel module, the left and right buttons are displayed, and the left and right buttons are hidden when left.

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

​ 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. The carousel will automatically play the picture without the mouse passing through the carousel.

​ 6. When the mouse is over, the carousel module will automatically play and stop.

window.addEventListener('load', function() {
    // 1. 获取元素
    var arrow_l = document.querySelector('.arrow-l');
    var arrow_r = document.querySelector('.arrow-r');
    var focus = document.querySelector('.focus');
    var focusWidth = focus.offsetWidth;
    // 2. 鼠标经过focus 就显示隐藏左右按钮
    focus.addEventListener('mouseenter', function() {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        clearInterval(timer);
        timer = null; // 清除定时器变量
    });
    focus.addEventListener('mouseleave', function() {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        timer = setInterval(function() {
            //手动调用点击事件
            arrow_r.click();
        }, 2000);
    });
    // 3. 动态生成小圆圈  有几张图片,我就生成几个小圆圈
    var ul = focus.querySelector('ul');
    var ol = focus.querySelector('.circle');
    // console.log(ul.children.length);
    for (var i = 0; i < ul.children.length; i++) {
        // 创建一个小li 
        var li = document.createElement('li');
        // 记录当前小圆圈的索引号 通过自定义属性来做 
        li.setAttribute('index', i);
        // 把小li插入到ol 里面
        ol.appendChild(li);
        // 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件
        li.addEventListener('click', function() {
            // 干掉所有人 把所有的小li 清除 current 类名
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            // 留下我自己  当前的小li 设置current 类名
            this.className = 'current';
            // 5. 点击小圆圈,移动图片 当然移动的是 ul 
            // ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值
            // 当我们点击了某个小li 就拿到当前小li 的索引号
            var index = this.getAttribute('index');
            // 当我们点击了某个小li 就要把这个li 的索引号给 num  
            num = index;
            // 当我们点击了某个小li 就要把这个li 的索引号给 circle  
            circle = index;
            // num = circle = index;
            console.log(focusWidth);
            console.log(index);

            animate(ul, -index * focusWidth);
        })
    }
    // 把ol里面的第一个小li设置类名为 current
    ol.children[0].className = 'current';
    // 6. 克隆第一张图片(li)放到ul 最后面
    var first = ul.children[0].cloneNode(true);
    ul.appendChild(first);
    // 7. 点击右侧按钮, 图片滚动一张
    var num = 0;
    // circle 控制小圆圈的播放
    var circle = 0;
    // flag 节流阀
    var flag = true;
    arrow_r.addEventListener('click', function() {
        if (flag) {
            flag = false; // 关闭节流阀
            // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * focusWidth, function() {
                flag = true; // 打开节流阀
            });
            // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
            circle++;
            // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原
            if (circle == ol.children.length) {
                circle = 0;
            }
            // 调用函数
            circleChange();
        }
    });

    // 9. 左侧按钮做法
    arrow_l.addEventListener('click', function() {
        if (flag) {
            flag = false;
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * focusWidth + 'px';

            }
            num--;
            animate(ul, -num * focusWidth, function() {
                flag = true;
            });
            // 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
            circle--;
            // 如果circle < 0  说明第一张图片,则小圆圈要改为第4个小圆圈(3)
            // if (circle < 0) {
            //     circle = ol.children.length - 1;
            // }
            circle = circle < 0 ? ol.children.length - 1 : circle;
            // 调用函数
            circleChange();
        }
    });

    function circleChange() {
        // 先清除其余小圆圈的current类名
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        // 留下当前的小圆圈的current类名
        ol.children[circle].className = 'current';
    }
    // 10. 自动播放轮播图
    var timer = setInterval(function() {
        //手动调用点击事件
        arrow_r.click();
    }, 2000);

})

1.2.2. Throttle valve

Prevent the carousel button from being clicked continuously to cause the playback to be too fast.

Throttle valve purpose: When the content of the previous function animation is completed, execute the next function animation, so that the event cannot be triggered continuously.

The core implementation idea: use the callback function, add a variable to control, lock the function and unlock the function.

Start setting a variable var flag = true;

If(flag){flag = false; do something} close the faucet

After the animation is executed using the callback function, flag = true to open the faucet

1.2.3. Case: back to top

  1. back to top with animation
  2. At this point, we can continue to use our encapsulated animation function
  3. Just change all the left-related values ​​to be related to the vertical scrolling distance of the page.
  4. How much the page scrolls, you can get it through window.pageYOffset
  5. Finally, the page scrolls, using window.scroll(x,y)
  //1. 获取元素
        var sliderbar = document.querySelector('.slider-bar');
        var banner = document.querySelector('.banner');
        // banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
        var bannerTop = banner.offsetTop
            // 当我们侧边栏固定定位之后应该变化的数值
        var sliderbarTop = sliderbar.offsetTop - bannerTop;
        // 获取main 主体元素
        var main = document.querySelector('.main');
        var goBack = document.querySelector('.goBack');
        var mainTop = main.offsetTop;
        // 2. 页面滚动事件 scroll
        document.addEventListener('scroll', function() {
    
    
                // console.log(11);
                // window.pageYOffset 页面被卷去的头部
                // console.log(window.pageYOffset);
                // 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
                if (window.pageYOffset >= bannerTop) {
    
    
                    sliderbar.style.position = 'fixed';
                    sliderbar.style.top = sliderbarTop + 'px';
                } else {
    
    
                    sliderbar.style.position = 'absolute';
                    sliderbar.style.top = '300px';
                }
                // 4. 当我们页面滚动到main盒子,就显示 goback模块
                if (window.pageYOffset >= mainTop) {
    
    
                    goBack.style.display = 'block';
                } else {
    
    
                    goBack.style.display = 'none';
                }

            })
            // 3. 当我们点击了返回顶部模块,就让窗口滚动的页面的最上方
        goBack.addEventListener('click', function() {
    
    
            // 里面的x和y 不跟单位的 直接写数字即可
            // window.scroll(0, 0);
            // 因为是窗口滚动 所以对象是window
            animate(window, 0);
        });

1.2.4. Case: Jintou Cloud Case

  1. Use animation functions to do animation effects
  2. The original somersault cloud started at 0
  3. When the mouse passes through a small li, the offsetLeft position of the current small li can be used as the target value.
  4. When the mouse leaves a small li, set the target value to 0
  5. If a small li is clicked, the current position of the li is stored as the starting position of the somersault cloud.
 window.addEventListener('load', function() {
    
    
            // 1. 获取元素
            var cloud = document.querySelector('.cloud');
            var c_nav = document.querySelector('.c-nav');
            var lis = c_nav.querySelectorAll('li');
            // 2. 给所有的小li绑定事件 
            // 这个current 做为筋斗云的起始位置
            var current = 0;
            for (var i = 0; i < lis.length; i++) {
    
    
                // (1) 鼠标经过把当前小li 的位置做为目标值
                lis[i].addEventListener('mouseenter', function() {
    
    
                    animate(cloud, this.offsetLeft);
                });
                // (2) 鼠标离开就回到起始的位置 
                lis[i].addEventListener('mouseleave', function() {
    
    
                    animate(cloud, current);
                });
                // (3) 当我们鼠标点击,就把当前位置做为目标值
                lis[i].addEventListener('click', function() {
    
    
                    current = this.offsetLeft;
                });
            }
        })

1.3. Touch screen events

1.3.1. Overview of Touch Screen Events

The compatibility of mobile browsers is good. We don't need to consider the compatibility of JS before, and we can use native JS to write the effect with confidence, but the mobile terminal also has its own unique features. For example, the touch screen event touch (also called touch event), both Android and IOS have.

The touch object represents a touch point. The touch point may be a finger or a stylus. Touch events respond to user finger (or stylus) operations on the screen or trackpad.

Common touch screen events are as follows:

insert image description here

1.3.2. Touch Event Object (TouchEvent)

TouchEvent is a class of events that describe the state change of a finger on a touch plane (touch screen, touchpad, etc.). This type of event is used to describe one or more touchpoints, allowing developers to detect movement of touchpoints, increase and decrease of touchpoints, etc.

The three events touchstart, touchmove, and touchend will have their own event objects.

Touch Event Object Focus Let's look at a list of three common objects:

insert image description here

因为平时我们都是给元素注册触摸事件,所以重点记住 targetTocuhes

1.3.3. Case: dragging elements on the mobile side

  1. touchstart, touchmove, touchend can drag elements

  2. But dragging the element requires the coordinate value of the current finger. We can use pageX and pageY in targetTouches[0]

  3. The principle of dragging on the mobile terminal: During the movement of the finger, the distance of the finger movement is calculated. Then use the original position of the box + the distance moved by the finger

  4. Distance the finger moved: the position in the swipe minus the position the finger first touched

    Drag element triad:

    (1) Touch element touchstart: Get the initial coordinates of the finger, and at the same time get the original position of the box

    (2) Move the finger touchmove: Calculate the sliding distance of the finger and move the box

    (3) Leave the finger touchend:

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

おすすめ

転載: blog.csdn.net/JHXL_/article/details/121336914