O sistema leva você a aprender WebAPIs - animação (6ª palestra)

APIs da Web

Os objetivos de aprendizagem deste artigo:

Capacidade de encapsular funções de animação simples

Pode entender o encapsulamento da animação facilitada

Capacidade de usar funções de animação

Ser capaz de escrever um caso de carrossel de páginas da web

Capacidade de escrever eventos de tela de toque móvel

1.1. Encapsulamento da função de animação

1.1.1 Princípio do efeito de flexibilização

Facilitar a animação é mudar a velocidade do movimento do elemento, o mais comum é deixar a velocidade parar lentamente

Ideias:

  1. Deixe a distância da caixa diminuir gradualmente a cada vez, e a velocidade cairá lentamente.
  2. Algoritmo principal: (valor alvo - posição atual) / 10 como o passo de distância para cada movimento
  3. As condições para parar são: Parar o cronômetro quando a posição atual da caixa for igual à posição alvo
  4. Observe que o valor da etapa precisa ser arredondado

1.1.2 Função de animação movendo-se entre vários valores de destino

A função de animação pode ser movida de 800 para 500.

Quando clicamos no botão, determinamos se o tamanho do passo é positivo ou negativo

1. Se for um valor positivo, o tamanho do passo é arredondado para cima

2. Se for um valor negativo, o tamanho do passo é arredondado para cima

1.1.3 Adicionar função de retorno de chamada à função dinâmica

O princípio da função de retorno de chamada: função pode ser usada como parâmetro. Passe essa função como parâmetro para outra função, e depois que essa função for executada, execute a função passada, esse processo é chamado de retorno de chamada.

A posição em que a função de retorno de chamada é gravada: a posição em que o cronômetro termina.

1.1.4 Código da versão completa da animação:

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. Casos comuns de efeitos especiais de páginas da web

1.2.1 Caso: carrossel de páginas da web

A imagem de carrossel, também conhecida como imagem de foco, é um efeito de página da Web relativamente comum em páginas da Web.

Requisitos funcionais:

1. Quando o mouse passa pelo módulo carrossel, os botões esquerdo e direito são exibidos e os botões esquerdo e direito ficam ocultos quando esquerdos.

2. Clique no botão à direita uma vez, e a imagem será reproduzida à esquerda, e assim por diante. O mesmo vale para o botão à esquerda.

3. Enquanto a imagem está sendo reproduzida, o pequeno módulo de círculo abaixo muda junto com ela.

4. Clique no pequeno círculo para reproduzir a imagem correspondente.

5. O carrossel reproduzirá automaticamente a imagem sem que o mouse passe pelo carrossel.

6. Quando o mouse terminar, o módulo carrossel será reproduzido e parado automaticamente.

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. Válvula de aceleração

Evite que o botão do carrossel seja clicado continuamente para fazer com que a reprodução seja muito rápida.

Finalidade da válvula de estrangulamento: Quando o conteúdo da animação da função anterior estiver concluído, execute a próxima animação da função, para que o evento não possa ser acionado continuamente.

A ideia principal da implementação: use a função de retorno de chamada, adicione uma variável para controlar, bloqueie a função e desbloqueie a função.

Comece configurando uma variável var flag = true;

If(flag){flag = false; faça alguma coisa} feche a torneira

Depois que a animação for executada usando a função de retorno de chamada, flag = true para abrir a torneira

1.2.3. Caso: voltar ao topo

  1. voltar ao topo com animação
  2. Neste ponto, podemos continuar a usar nossa função de animação encapsulada
  3. Basta alterar todos os valores relacionados à esquerda para serem relacionados à distância de rolagem vertical da página.
  4. Quanto a página rola, você pode obtê-lo através de window.pageYOffset
  5. Finalmente, a página rola, usando 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. Estojo: Estojo Jintou Cloud

  1. Use funções de animação para fazer efeitos de animação
  2. A nuvem de cambalhota original começou em 0
  3. Quando o mouse passa por um pequeno li, a posição offsetLeft do pequeno li atual pode ser usada como valor de destino.
  4. Quando o mouse deixa um pequeno li, defina o valor alvo para 0
  5. Se um pequeno li for clicado, a posição atual do li é armazenada como a posição inicial da nuvem de cambalhota.
 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. Eventos de tela sensível ao toque

1.3.1. Visão geral dos eventos da tela sensível ao toque

A compatibilidade dos navegadores móveis é boa. Não precisamos considerar a compatibilidade do JS no passado, e podemos usar JS nativo para escrever o efeito com confiança, mas o terminal móvel também tem seus próprios recursos exclusivos. Por exemplo, o evento touch screen touch (também chamado de evento touch), tanto o Android quanto o IOS possuem.

O objeto de toque representa um ponto de toque. O ponto de toque pode ser um dedo ou uma caneta. Os eventos de toque respondem às operações do dedo do usuário (ou caneta) na tela ou no trackpad.

Os eventos comuns da tela de toque são os seguintes:

insira a descrição da imagem aqui

1.3.2. Objeto de evento de toque (TouchEvent)

TouchEvent é uma classe de eventos que descreve a mudança de estado de um dedo em um plano de toque (touch screen, touchpad, etc.). Esse tipo de evento é usado para descrever um ou mais touchpoints, permitindo que os desenvolvedores detectem movimento de touchpoints, aumento e diminuição de touchpoints, etc.

Os três eventos touchstart, touchmove e touchend terão seus próprios objetos de evento.

Foco do objeto de evento de toque Vamos ver uma lista de três objetos comuns:

insira a descrição da imagem aqui

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

1.3.3. Caso: arrastando elementos no lado móvel

  1. touchstart, touchmove, touchend pode arrastar elementos

  2. Mas arrastar o elemento requer o valor da coordenada do dedo atual. Podemos usar pageX e pageY em targetTouches[0]

  3. O princípio de arrastar no terminal móvel: Durante o movimento do dedo, a distância do movimento do dedo é calculada. Em seguida, use a posição original da caixa + a distância movida pelo dedo

  4. Distância em que o dedo se moveu: a posição no furto menos a posição em que o dedo tocou pela primeira vez

    Arraste a tríade do elemento:

    (1) Touchstart do elemento de toque: obtenha as coordenadas iniciais do dedo e, ao mesmo tempo, obtenha a posição original da caixa

    (2) Mova o dedo touchmove: Calcule a distância de deslizamento do dedo e mova a caixa

    (3) Deixe o toque do dedo:

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

Acho que você gosta

Origin blog.csdn.net/JHXL_/article/details/121336914
Recomendado
Clasificación