English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Implementación de efectos de entrada y salida del ratón similares a Lagou.net con JavaScript

先上效果图(gif自己录制的,有点难看抱歉,工具licecap)

 

实现思路

 HTML结构

  <ul>
    <li>
      <div class="bg">
        <p>JS</p>
      </div>
    </li>
    .....
  </ul>

    li作为鼠标移入(mouseenter)和鼠标移出(mouseleave)的载体。

    div作为动画执行的载体。

CSS

    div采用absolute定位,通过top、left改变它的位置。

    由于div的top、left可能会超出li的大小,所以要设置li的overflow:hidden;

JS

    1、采用JS操纵CSS3 animación de transición

    2、如何判断鼠标移入移除的方向

鼠标坐标的相关知识

MouseEvent对象

下面介绍几个MouseEvent中坐标的相关知识:

    (clientX, clientY): 以可视区域为参考系的坐标。

    (pageX, pageY): 以整个页面(包括滚动条卷出的区域)为参考系的坐标。

    (screenX, screenY): 以你的电脑屏幕为参考系的坐标。

    获取某个元素内部的坐标

  function pointTo(element, e) {
    var elementBox = element.getBoundingClientRect();
    devolver {
      x: e.clientX - elementBox.left,
      y: e.clientY - elementBox.top
    };
  }

    calcular las coordenadas del extremo superior izquierdo del elemento

  function startPoint(element){
    var x = 0,y = 0;
    while(element != null) {
      x += element.offsetLeft;
      y += element.offsetTop;
      element = element.offsetParent;
    }
    devolver {
      x: x,
      y: y
    }
  }

    obtener el ancho y la altura del elemento (no lo considere como width y height, los principiantes suelen cometer errores)

  offsetHeight y offsetWidth

envoltura simple de CSS3 animación de transición

/* parámetros options: obj: objeto en movimiento speed: duración del movimiento (opcional) changeStyle: propiedades que se cambian, aquí pueden ser varias, por lo que se utiliza una función (opcional) callback: función de retroalimentación (opcional) */
  function animation(options){
    if(!options.obj) {
      return false;
    }
    //establecer el tiempo de duración predeterminado
    options.speed = options.speed || '.5s';
    options.obj.style.transition = "all " + options.speed + " suavidad-in-out";
    options.changeStyle.call(options.obj);
    var flag = false;
    options.obj.addEventListener('transitionend',function(){
      //Aquí se debe a que el evento 'transitionend' se ejecuta varias veces después de que se complete la animación de cada propiedad, por lo que debemos asegurarnos de que se ejecute solo una vez.
      if(!flag) {
        options.callback && options.callback();
      }
    },false);
  }

cómo determinar la dirección

Aquí se utilizan conceptos relacionados con la tangente en matemáticas, dibujé un gráfico, no sé si pueden entenderlo claramente: (horrible...)

 

obtener la dirección de movimiento del elemento

  function getDirection(element,startPoint,pagePoint){
    var halfWidth = element.offsetWidth / 2,halfHeight = element.offsetHeight / 2;
    //Obtener el punto central
    var center = {
      x: startPoint.x + halfWidth,
      y: startPoint.y + halfHeight
    }
    //Obtener la distancia del ratón desde el centro
    var disX = pagePoint.x - center.x;
    var disY = pagePoint.y - center.y;
    if(disY < 0 && Math.abs(disY / disX) >= 1) {
      //arriba
      return 1;
    }
    else if(disY > 0 && Math.abs(disY / disX) >= 1) {
      //abajo
      return 2;
    }
    else if(disX < 0 && Math.abs(disY / disX) < 1) {
      //izquierda
      return 3;
    }
    else {
      //derecha
      return 4;
    }
  }

El código para iniciar el evento, con comentarios

/* Los parámetros en options: el portador del evento desencadenado: targetElement El portador de la animación: animationElement */
  function HoverAction(options) {
    if(!options.targetElement || !options.animationElement) {
      return false;
    }
    this.targetElement = options.targetElement;
    this.animationElement = options.animationElement;
    this.timeId = null;
    this.speed = "0.3s";
  }
  HoverAction.prototype.addEvent = function() {
    //Guardar la referencia de this
    var _this = this;
    _this.targetElement.addEventListener('mouseenter',function(e){
      //Obtener las coordenadas del ratón
      var point = {
        x: e.pageX,
        y: e.pageY
      }
      console.log(point);
      //Obtener la dirección
      var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);
      clearTimeout(_this.timeId);
      //Cancelar la animación de transición (para evitar que se active el efecto de transición cuando se restablece la posición del elemento de animación)
      _this.animationElement.style.transition = "";
      //Obtener la dirección del movimiento, para determinar la posición de inicio del elemento de animación
      switch(dir){
        case 1:
          _this.animationElement.style.top = ""-100%";
          _this.animationElement.style.left = "0";
          break;
        case 2:
          _this.animationElement.style.top = ""100%";
          _this.animationElement.style.left = "0";
          break;
        case 3:
          _this.animationElement.style.top = "0";
          _this.animationElement.style.left = "-100%";
          break;
        case 4:
          _this.animationElement.style.top = "0";
          _this.animationElement.style.left = "100%";
          break;
      }
      //Ejecución asíncrona
      _this.timeId = setTimeout(function(){
        animation({
          obj: _this.animationElement,
          speed: _this.speed,
          changeStyle: function(){
            this.style.top = "0";
            this.style.left = "0";
          }
        });
      },20);
    },false);
    _this.targetElement.addEventListener('mouseleave',function(e){
      var left,top;
      var point = {
        x: e.pageX,
        y: e.pageY
      }
      clearTimeout(_this.timeId);
      _this.animationElement.style.transition = "";
      var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);
      switch(dir) {
        case 1:
          top = '-100%';
          left = '0';
          break;
        case 2:
          top = '100%';
          left = "0";
          break;
        case 3:
          left = "-100%";
          top = "0";
          break;
        case 4:
          left = "100%";
          top = "0";
          break;
      }
      _this.timeId = setTimeout(function(){
        animation({
          obj: _this.animationElement,
          speed: _this.speed,
          changeStyle: function(){
            this.style.top = top;
            this.style.left = left;
          }
        });
      },20);
    },false);
  }

Resumen

Este es el contenido completo de este artículo, espero que el contenido de este artículo pueda ayudarles en su aprendizaje o trabajo, si tienen alguna pregunta, pueden dejar comentarios para intercambiar.

Te gustará