2010-09-02 9 views
9

Estoy tratando de simular el efecto en el que sobrevivo en una imagen, una imagen semitransparente superpuesta se desvanecerá desde la dirección de donde vino su mouse. Viceversa cuando el mouse deja la imagen (fadeout + se aleja)Animación de jQuery para un elemento emergente con 'dirección del mouse'

He preparado un test page para esto. Adelante y compruébalo, aclarará cuál es el efecto deseado.

he definido una estructura HTML para esto:

<div class="overlayLink"> 
     <img src="assets/work/thumbnails/kreatude.jpg" alt="Kreatude" /> 
     <div class="overlayLink_overlay_bg">&nbsp;</div> 
     <div class="overlayLink_overlay_fg"> 
      <span class="overlayLink_overlay_link"><a href="#">View Case Study</a></span> 
      <div class="top">&nbsp;</div> 
      <div class="left">&nbsp;</div> 
      <div class="right">&nbsp;</div> 
      <div class="bottom">&nbsp;</div> 
     </div> 
    </div> 

y la siguiente JS (estoy usando jQuery):

jQuery(document).ready(function() { 
    ourWork(); 
}); 

function ourWork(){ 
    var inHandler = function(){ 
     var blue_bg = jQuery(this).find('.overlayLink_overlay_bg'); 
     var divClass = inClass; 

     blue_bg.stop(true,true).fadeIn(); 
     var ml,mt; 
     if(divClass == 'left'){ 
      ml = -260; 
      mt = 0; 
     } 
     else if(divClass == 'right'){ 
      ml = 260; 
      mt = 0; 
     } 
     else if(divClass == 'top'){ 
      ml = 0; 
      mt = -140; 
     } 
     else if(divClass == 'bottom'){ 
      ml = 0; 
      mt = 140; 
     }  

     //positioning 
     jQuery(this).find('a').css({ 
      'marginLeft': ml + 'px', 
      'marginTop' : mt + 'px' 
     }); 


     //animation 
     jQuery(this).find('a').stop(true,true).animate({ 
      "marginLeft": "0px", 
      "marginTop": "0px" 
     }, "slow"); 
    } 
    var outHandler = function(){ 
     var blue_bg = jQuery(this).find('.overlayLink_overlay_bg'); 
     var divClass = outClass; 

     blue_bg.stop(true,true).fadeOut(); 
     var ml,mt; 
     if(divClass == 'left'){ 
      ml = -260; 
      mt = 0; 
     } 
     else if(divClass == 'right'){ 
      ml = 260; 
      mt = 0; 
     } 
     else if(divClass == 'top'){ 
      ml = 0; 
      mt = -140; 
     } 
     else if(divClass == 'bottom'){ 
      ml = 0; 
      mt = 140; 
     }   

     //animation 
     jQuery(this).find('a').stop(true,true).animate({ 
      "marginLeft": ml + "px", 
      "marginTop": mt + "px" 
     }, "slow"); 

    } 

    var inClass, outClass; 
    jQuery('.overlayLink_overlay_fg div').hover(function(){   
     inClass = jQuery(this).attr('class'); 
    },function(){  
     outClass = jQuery(this).attr('class'); 
    }); 

    jQuery('.overlayLink').mouseenter(inHandler).mouseleave(outHandler); 
} 

explicación:

Básicamente tengo cuatro divs posicionados absolutos en la parte superior de la imagen para saber la dirección (izquierda, arriba, abajo, derecha) cuando controlo sobre uno de esos 4 div (.overlayLink_o verlay_fg div) Puse el nombre de la clase del div oculto en una variable (var inClass y var outclass)

Una vez sobrevuelo el div que cubre el área de la imagen (.overlayLink) solicito la dirección del inClass o superar a la variable y realizar la animación (inHandler, outHandler)

sin embargo todo esto parece que funciona, que es un poco glitchy cuando se mueve el puntero del ratón muy rápido, ahora estoy pidiendo cuál es el problema (que está causando el problemas técnicos) y cómo podría solucionarse con mi código actual.

Gracias de antemano

+0

Hay muchos problemas técnicos en la página que ha vinculado anteriormente, esto es suyo ¿verdad? Si bajé desde la cima, funciona. Luego a la izquierda funciona. Luego, si bajé desde la parte superior otra vez, funciona, pero al volver a la izquierda, aumenta la superposición. Luego, si entro por la izquierda después de eso, la superposición proviene de la parte superior. No importa qué tan rápido lo haga. –

+0

tienes razón, no te diste cuenta que era tan complicado. Y sí, esta es mi página. Sin embargo, debe haber alguna razón lógica por la que esto sucede. Si reviso mi código no puedo ver el error lógico, lo cual me molesta bastante. – Ayrton

+0

Simplemente no lo hagas. No es justo para los usuarios táctiles. –

Respuesta

44

Quizás debas considerar no usar los divs como "puntos de acceso", pero usa algo de matemática y Javascript para encontrar el punto donde el mouse entra y sale de un div. Esto evita problemas de superposición/lagunas. El código a continuación básicamente divide un div en 4 zonas triangulares. Cada zona devuelve un número cuando el mouse se mueve sobre él. El código necesita algunos ajustes finos y debes decidir por ti mismo dónde vincular y desvincular los eventos. Pero creo que le quita la mayoría de sus problemas de parpadeo.

$(".overlayLink").bind("mouseenter mouseleave",function(e){ 

/** the width and height of the current div **/ 
var w = $(this).width(); 
var h = $(this).height(); 

/** calculate the x and y to get an angle to the center of the div from that x and y. **/ 
/** gets the x value relative to the center of the DIV and "normalize" it **/ 
var x = (e.pageX - this.offset().left - (w/2)) * (w > h ? (h/w) : 1); 
var y = (e.pageY - this.offset().top - (h/2)) * (h > w ? (w/h) : 1); 

/** the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);**/ 
/** first calculate the angle of the point, 
add 180 deg to get rid of the negative values 
divide by 90 to get the quadrant 
add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/ 
var direction = Math.round((((Math.atan2(y, x) * (180/Math.PI)) + 180)/90) + 3) % 4; 


/** do your animations here **/ 
switch(direction) { 
case 0: 
    /** animations from the TOP **/ 
break; 
case 1: 
    /** animations from the RIGHT **/ 
break; 
case 2: 
    /** animations from the BOTTOM **/ 
break; 
case 3: 
    /** animations from the LEFT **/ 
break; 
}}); 

por supuesto, la notación abreviada para obtener la dirección debe ser:

var direction = Math.round(Math.atan2(y, x)/1.57079633 + 5) % 4 

donde 1,57 es ... Math.PI/2 Esto es mucho más efiicient poco más difícil para mí explicar ya que salta la conversión de grados.

+1

genio! muchas gracias. – David

+0

también, si el JavaScript nativo this.offsetTop no informa correctamente, usando $ (this) .offset(). Top funcionó. Moveré el cuerpo en un eje de traducción Y, lo que daña las lecturas de desplazamiento correctas. Solo un fyi. – Abbey

+1

Hola Caspar, puedo entender el concepto de calcular el xey para obtener un ángulo en el centro del div, pero no sé por qué necesito '(w> h? (H/w): 1)' ? ¿Puedes ayudarme a entender eso? Pensé en normalizarlo '(e.pageX - this.offsetLeft - (w/2))' esto es suficiente – Sean

0

Más que rodea la imagen con divs posición absoluta, es posible que trate de hacer esto con un mapa de imagen, adjuntando a los manipuladores de las áreas definidas. Simplemente defina que las áreas de borde sean lo suficientemente gruesas para que se detecte el movimiento del mouse incluso si se mueve con bastante rapidez.

+0

¿es esto solo una idea o se considera una buena práctica? – Ayrton

+0

Tenga en cuenta a qué se refiere con "solo un pensamiento". Rodear sus imágenes con divs completamente posicionados es un truco ingenioso. Mientras que el mapa de imagen y la imagen son integrales entre sí y ofrecen un diseño más limpio con una mejor encapsulación y un diseño de página menos complicado. – Tim

+0

Además, con un mapa de imagen puede ajustar más fácilmente el grosor de las áreas de borde "calientes" invisibles, para detectar mejor el mouse sin afectar el diseño. – Tim

0

Si usted pasa el puntero del ratón rápidamente de izquierda a derecha de modo que cruce 3 rectángulos

 [ 1 ] [ 2 ] [ 3 ] 

el ratón va a ingresar en el rectángulo # 3 a través de su frontera izquierda div inmediatamente después de que haya salido rectángulo # 2 a través de su borde derecho div. Sin embargo, la asignación inClass = "left" outClass = "left" cuando se ingresa el rectángulo # 3 a través de su borde izquierdo div ANTES de que se haya disparado el outHandler para el rectángulo # 2.

0

Si me iban a implementar esta funcionalidad, así es como me lo planteo:

  1. crear áreas de mapa de imágenes que definen la parte superior, inferior, izquierda y derecha de las fronteras de la imagen.
  2. Para cada imagen donde desee esta inteligencia (es deciren qué lado se ingresó, de qué lado salió): a) rastree el sideEntered - este valor se asigna una sola vez; siempre que se ingrese un área de borde de mapa de imagen, su manejador de mouse consultará sideEntered y lo asignará solo si aún no se le ha asignado; b) realizar el seguimiento del lastSideTouched - cada vez que se introduce un área de mapa de imágenes en su mouseOverHandler reasigna esta variable c) cuando el ratón sale del rectángulo, el manejador de licencia consulta lastSideTouched y restablece sideEntered a null

Cada rectángulo debe tener sus propios controladores de manera que los dos valores importantes, sideEntered y lastSideTouched, son encapsulado dentro del alcance de su controlador.

+0

Consulte mi explicación a continuación sobre por qué el movimiento rápido está causando problemas técnicos. – Tim

0
  • cuál es el problema (que está causando los problemas técnicos)

Este código (y el uso de INCLASS & outclass) son problemáticos. Está cambiando el estado de las variables globales que se utilizan en los controladores de eventos.

var inClass, outClass; 
jQuery('.overlayLink_overlay_fg div').hover(function(){   
    inClass = jQuery(this).attr('class'); 
},function(){   
    outClass = jQuery(this).attr('class'); 
}); 

Este código se supone que outclass fue fijado por el div 'local', pero coulsd haber sido establecido por un div superior vecina

var outHandler = function(){   
    var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');   
    var divClass = outClass; 
  • cómo [podía] que podría ser fijado con mi código actual?

No lo administre como una única variable global, intente administrarlo con Mannor aislado.

Aquí está uno apprach: No he probado este código

jQuery('.overlayLink_overlay_fg div').hover(function() { 
     jQuery(this).parents('.overlayLink').attr('mouseEnterClass', jQuery(this).attr('class')); 
    }, function() { 
     jQuery(this).parents('.overlayLink').attr('mouseLeaveClass', jQuery(this).attr('class')); 
    }); 

En sus manipuladores, refrence estos nuevos datos.

var outHandler = function() { 
     var blue_bg = jQuery(this).find('.overlayLink_overlay_bg'); 
     var divClass = jQuery(this).attr('mouseLeaveClass'); 
     .... 
     } 

este woulod aborda la variable global. No estoy seguro de qué pasará si el evento 'hover' ocurre antes de que la animación se complete.

EDITAR: Se corrigieron los problemas con el código.

1

Fundamentalmente, los eventos de movimiento del mouse ocurren como una secuencia de puntos, no como una línea curva, ya que percibimos el movimiento en la pantalla. Cuanto más rápido mueva el mouse, más ancho será el espacio entre los puntos y mayor será el tamaño de los objetos que el mouse puede mover sin tocar. Entonces, idealmente, necesitas saber la dirección de la última posición del mouse antes de aterrizar en tu objeto y de allí calcular la dirección desde la que se acercó. es decir, necesita realizar un seguimiento constante de la posición del mouse en toda la página para asegurarse de que su efecto funcione correctamente todas las veces.

Cuestiones relacionadas