Las propiedades
layerX y
layerY del objeto event proporcionan las coordenadas x e y del ratón, relativas al elemento que dispara el evento. Dichas propiedades son soportadas por todos los navegadores modernos, salvo por Explorer que, como bien sabemos, maneja los eventos a su manera. En este caso, ese fantástico navegador utiliza las propiedades
offsetX y
offsetY, que son equivalentes a las anteriores.
Veamos un ejemplo de cómo obtener las coordenadas del ratón relativas a una imagen:
Como podemos apreciar, las coordenadas son relativas a la imagen y no al área de visualización de la página o viewport, como ocurriría si utilizáramos en su lugar las propiedades
clientX y
clientY del objeto event, complementadas con
self.pageXOffset y
self.pageYOffset y sus equivalentes para Explorer (document.body.scrollLeft/scrollTop o document.documentElement.scrollLeft/scrollTop, según el compatMode que usemos) para añadir el desplazamieno del scroll.
El código utilizado es el siguiente:
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>coordenadas imagen</title>
<style>
*{ margin:0; padding:0; font-size:10px; color#666; font-family:Verdana, Arial, Helvetica, sans-serif}
img{cursor:crosshair}
</style>
<script>
function getPos(e){
var ev=e || window.event;
var obj=ev.target || ev.srcElement;
obj.style.position='relative';
posX=ev.layerX || ev.offsetX || 0;
posY=ev.layerY || ev.offsetY || 0;
return {x:posX,y:posY}
}
</script>
</head>
<body>
<img src="img/38.jpg" width="400" height="400" onmousemove="var pos=getPos(event);document.getElementById('log').innerHTML='x: '+pos.x+', y: '+pos.y" />
<div id="log">pase el mouse sobre la imagen</div>
</body>
</html>
Si tomamos ese código como base y agregamos algunos estilos css y regla de tres simple, podemos fácilmente conseguir un efecto lupa semejante a este:
El código que utilizamos para lograrlo es el siguiente:
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Lupa Sencilla</title>
<style>
*{ margin:0; padding:0; font-size:10px; color#666; font-family:Verdana, Arial, Helvetica, sans-serif}
#lupa{width:167px;height:167px;position:absolute;border:1px solid #000;overflow:hidden;left: 258px;top:0px;background-color:#999}
#im{position: relative; left:0;top:0}
#im0{cursor:crosshair}
</style>
<script>
function t(id){return document.getElementById(id);}
function addEvent(obj,fun,type){
if(obj.addEventListener){
obj.addEventListener(type,fun,false);
}else if(obj.attachEvent){
var f=function(){
fun.call(obj,window.event);
}
obj.attachEvent('on'+type,f);
obj[fun.toString()+type]=f;
}else{
obj['on'+type]=fun;
}
}
function getPos(e){
var ev=e || window.event;
var obj=ev.target || ev.srcElement;
obj.style.position='relative';
posX=ev.layerX || ev.offsetX || 0;
posY=ev.layerY || ev.offsetY || 0;
return {x:posX,y:posY}
}
function css(id,prop){
if(window.getComputedStyle){
return document.defaultView.getComputedStyle(t(id),null).getPropertyValue(prop);
}else{
var re = /(-([a-z]){1})/g;
if (prop == 'float') prop = 'styleFloat';
if (re.test(prop)) {
prop = prop.replace(re, function () {
return arguments[2].toUpperCase();
});
}
return t(id).currentStyle[prop] ? t(id).currentStyle[prop] : null;
}
}
function cambiar(pos,rel,e,a,a2,w,h){
var al=parseInt(a);
var al2=parseInt(a2);
if(pos.x<(al/2)/rel)
pos.x=(al/2)/rel;
if(pos.y<(al2/2)/rel)
pos.y=(al2/2)/rel;
if(pos.x>(w)-(al/2)/rel)
pos.x=(w)-(al/2)/rel;
if(pos.y>(h)-(al2/2)/rel)
pos.y=(h)-(al2/2)/rel;
t('im').style.left=-(rel*pos.x)+(al/2)+'px';
t('im').style.top=-(rel*pos.y)+(al2/2)+'px';
}
onload=function(){
addEvent(
t('im0'),
function(e){
var al2=css('lupa','height');
var al=css('lupa','width');
var pos=getPos(e);
cambiar(pos,(t('im').width)/this.width,e,al,al2,this.width,this.height);
},
'mousemove'
);
}
</script>
</head>
<body>
<img id="im0" src="img/18.jpg" width="250" height="167" />
<div id="lupa"><img id="im" src="img/18.jpg" width="500" /></div>
<div>recorra con el mouse la primera imagen</div>
</body>
</html>
El truco consiste en
enmascarar la imagen a tamaño completo con una capa con overflow hidden, y desplazarla (seguimos hablando de la imagen), en sentido inverso al movimiento del mouse, la misma distancia en pixeles respecto de su ubicación inicial en las coordenadas 0,0 de la capa, obtenida con layerX y layerY (y sus análogas para Explorer) durante el evento onmousemove, pero recalculada en función a la diferencia de proporción entre la imagen pequeña y la ampliada.
Adicionalmente, debemos
frenar el movimiento al llegar a los límites de la imagen pequeña, para no mostrar blancos en la visualización de la ampliación.