2009-07-18 17 views
17

Tengo elementos que están debajo de un elemento con opacidad: 0.5 en los que deseo poder hacer clic. ¿Cómo puedo hacer clic en "atravesar" el elemento superior?registrando clics en un elemento que está debajo de otro elemento

Aquí hay un ejemplo que demuestra mi problema. Haga clic en los cuadros para activarlos y desactivarlos. Puede editarlo on jsbin para probar su solución.

Puntos de bonificación si puede hacer que los recuadros alternen al desplazarse.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<title>Sandbox</title> 
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 
<style type="text/css" media="screen"> 
body { background-color: #000; } 
.box {width: 50px; height: 50px; border: 1px solid white} 
.highlight {background-color: yellow;} 
</style> 
<script type="text/javascript"> 
var dthen = new Date(); 
$('<div id="past">').css({'height': (dthen.getMinutes()*60)+dthen.getSeconds() +'px' 
      ,'position': 'absolute' 
      ,'width': '200px' 
      ,'top': '0px' 
      ,'background-color': 'grey' 
      ,'opacity': '0.5' 
      }) 
     .appendTo("#container"); 

setInterval(function(){ 
    dNow = new Date(); 
    $('#past').css('height', ((dNow.getSeconds()+(dNow.getMilliseconds()/1000))*50)%300 +'px'); 
},10) 

$(".box").click(function(){ 
     $(this).toggleClass("highlight"); 
    }); 
</script> 
</head> 
<body> 
    <div id="container"> 
    <div class="box" style="position:absolute; top: 25px; left: 25px;"></div> 
    <div class="box" style="position:absolute; top: 50px; left: 125px;"></div> 
    <div class="box" style="position:absolute; top: 100px; left: 25px;"></div> 
    <div class="box" style="position:absolute; top: 125px; left: 125px;"></div> 
    <div class="box" style="position:absolute; top: 225px; left: 25px;"></div> 
    <div class="box" style="position:absolute; top: 185px; left: 125px;"></div> 
    </div> 
</body> 
</html> 
+1

No creo que estamos aquí para escribir una solución completa para usted. Con las sugerencias que figuran a continuación, debe implementar la solución usted mismo. SO no es una tienda de consultoría gratuita. –

+3

No puedo creer que soy la única persona que alguna vez querrá hacer esto. Por lo tanto, creo que cualquier código que demuestre cómo hacerlo se utilizará más allá de lo planificado. No veo ningún problema con pedir código para hacer esto. –

+1

sam, también use addClass en lugar de todas esas configuraciones usando .css – redsquare

Respuesta

16

OK, así que hay 2 cosas que creo que haría: (1) una respuesta CSS3, que no está aunque ampliamente adoptado, y (2) un plan de copia de seguridad de Javascript para el resto. (no estoy seguro de qué hacer con los usuarios sin JS en los navegadores más antiguos que no son compatibles con la parte de CSS). Sigue leyendo ...

Primero: Utilice el código CSS 3 para hacer que el elemento superior 'invisible' al ratón interacción:

pointer-events: none; 

Esto no es sin embargo varios navegadores compatibles. Solo funciona en SVG & Elementos HTML en Gecko & Navegadores de Webkit, pero solo en elementos SVG en Opera y nada en IE.

por el MDN:

Las propiedades de CSS puntero-events permite autores para controlar si o cuando un elemento puede ser el objetivo de un evento del ratón. Esta propiedad se usa para especifique bajo qué circunstancia (si es alguno) un evento de mouse debe pasar "por" un elemento y destino sea lo que sea "debajo" de ese elemento.

Así es que la documentación: https://developer.mozilla.org/en/css/pointer-events

Segundo: Usar algo de JavaScript detección de características para aquellos navegadores que aún no admiten esta CSS. Tendrás que hacer tu propia, similar a Modernizr, ya que aún no prueba esto (que yo sepa). La idea es crear un elemento, aplicarle el CSS de eventos de puntero, verificarlo, y si el navegador admite la función, obtendrá el resultado esperado, en lugar de algo nulo o indefinido; luego destruye el elemento. De todos modos, una vez que tiene detección de características, puede usar jQuery o similar para adjuntar un oyente al elemento superior y asignarle un clic para hacer clic a través de otra cosa. Consulte jQuery y use la función click() para obtener más información (no hay suficiente reputación para publicar el enlace, sry).

Si consigo momento posterior, que podría ser capaz de trabajar hasta una rápida jsFiddle en él. Espero que esto ayude.

+0

¡Esto funciona! Compare la solución [point-events] (http://jsbin.com/limesat/edit?html,css,js,output) con la [solución original] (http://jsbin.com/pefop/edit?html, css, js, salida). Por supuesto, los puntero-eventos no existían cuando lo pregunté por primera vez en 2009. [IE11 ​​fue la primera versión en admitir puntero-eventos] (http://caniuse.com/#search=pointer-events) y eso salió en 2013. –

+0

Si necesita apoyar IE10 o inferior, Modernizr ahora parece tener una prueba para CSS Pointer Eventos –

+0

Esto también resuelve el problema de vuelo estacionario. Simplemente puede adjuntar estilos a '.box: hover' y todavía se activará si está debajo del elemento #past. –

20

Si elemento de la cima está contenido dentro del elemento continuación, puede dejar que la "burbuja a través" del evento. Si no es así, debe activar el clic manualmente. No hay forma de desactivar el controlador de eventos simplemente haciendo clic.

desencadenar el evento de forma manual, se puede hacer esto:

$("#topelement").click(function() { 
    $("#elementbelow").click(); 
    return false; 
}); 

EDITAR (respuesta a los comentarios):

enumerar todas las cajas, se puede hacer esto (de la parte superior de mi . cabeza ninguna prueba, ni siquiera podía estar libre de errores de sintaxis)

$("#topelement").click(function(e) { 
    $(".box").each(function() { 
     // check if clicked point (taken from event) is inside element 
     var mouseX = e.pageX; 
     var mouseY = e.pageY; 
     var offset = $(this).offset; 
     var width = $(this).width(); 
     var height = $(this).height(); 

     if (mouseX > offset.left && mouseX < offset.left+width 
      && mouseY > offset.top && mouseY < offset.top+height) 
     $(this).click(); // force click event 
    }); 
}); 
+0

Debería enumerar todos los elementos DOM para ver si el punto cliqueado está dentro de uno o más elementos. No hay manera de que el navegador puede hacer esto por usted –

+0

Gracias que funcionó un regalo: http://jsbin.com/pefop/edit –

2

he modificado el código desde arriba en la función jQuery, alguien podría encontrar útil:

Buscar alternativa clic sobre elementos:

$('.child').click(function(e) { 
    $(this).siblingsUnderMouse(e).each(fn); 
}); 

Si desea ignorar los píxeles transparentes en imágenes:

$('.child').click(function(e) { 
    $(this).siblingsUnderMouse(e).each(function() { 
     var clickOnVisiblePixel = $(this).isOnVisiblePixel(e); 
    }); 
}); 

Código:

$.fn.reverse = [].reverse; 
$.fn.siblingsUnderMouse = function(e, filter) 
{ 
    filter = filter || '*'; 

    var arr = $(); 
    this.parent().children().filter(filter).reverse().each(function() 
    { 
     var t = $(this); 
     // check if clicked point (taken from event) is inside element 
     var x = (e.pageX - t.offset().left).toFixed(); 
     var y = (e.pageY - t.offset().top).toFixed(); 
     var w = t.width(); 
     var h = t.height(); 

     if (x < 0 || x >= w || y < 0 || y >= h) 
      return; 

     arr.push(t); 
    }); 
    return arr; 
} 

$.fn.isOnVisiblePixel = function(e) 
{ 
    if (e.type == 'mouseleave') return false; 

    var t = this[0]; 
    if (!t || t.tagName != 'IMG') 
     t = this.find('img')[0]; 
    if (!t) return; 

    var w = $(t).width(); 
    var h = $(t).height(); 
    var o = $(t).offset(); 
    var x = (e.pageX - o.left).toFixed(); 
    var y = (e.pageY - o.top).toFixed(); 
    if (x < 0 || y < 0 || x >= w || y >= h) 
     return false; 

    var c = $('<canvas>')[0]; 
    c.width = w; 
    c.height = h; 

    var ctx = c.getContext('2d'); 
    ctx.drawImage(t, 0, 0, w, h); 

    var a = ctx.getImageData(x, y, 1, 1).data[3]; 
    return (a > 128); 
} 
1

Creo que Leland recibe el golpe correcto. En mi caso he resuelto utilizando sólo CSS y se puede insertar puntero-eventos: Ninguno a su #past elemento.

Cuestiones relacionadas