Bien. Entonces en vez de "sumar el rojo", vamos a "restar los otros". Así queda el rojo (o el verde) sólo, y se ve el cambio.
Código:
<html xmlns:v="urn:schemas-microsoft-com:vml">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>SPOT CON Compositor Filter 8.</title>
<style type=text/css>
v\:* {behavior: url(#default#VML); }
body {font-size: 100%; background: black; color: red;
font-weight: bold; }
</style>
<script type=text/javascript>
var X = 0;
var Y = 0;
var cursor = "move";
var destino ="#";
var titulo = "";
function mueve(evento){
var alfa = document.getElementById("caja");
var bravo = document.getElementById("spot");
X = evento.x ;
Y = evento.y ;
if ((X>305 && Y>80) && (X<380 && Y<190)) /*coordenadas cabeza*/ {
cursor = "pointer";
destino = "http://img41.imageshack.us/img41/3221/metropolis04.jpg";
titulo = "Cabeza."
bravo.fillcolor = "#ff00ff";
}
else {
cursor = "move";
destino =
"http://img710.imageshack.us/slideshow/webplayer.php?id=antoniosegui.jpg";
titulo = "Colección.";
bravo.fillcolor = "#00cccc";
}
bravo.style.left = X - 50 + "px"; // '50' es el radio del spot en px
bravo.style.top = Y - 50 + "px";
alfa.style.cursor = cursor;
alfa.title = titulo;
}
function lleva(){
window.location = destino;
}
function inicia(){
capa0.filters.item(0).Apply(); // aplica el filtro a la primera capa
capa0.innerHTML = capa1.innerHTML; // agrega la segunda capa
}
onload = inicia
</script>
</head>
<BODY>
<h1>Simula un <em>spot</em> sobre la imagen que marca el área activa
cambiando de color. (IE8)</h1>
<div style="width: 640px; height: 480px; position: relative;
margin: auto; "
onclick="lleva()" onmousemove="mueve(event)" id="caja">
<div id="capa0"
style="filter:
progid:DXImageTransform.Microsoft.Compositor(function=8, duration=20);
position: absolute; top: 0; left: 0; width: 640px; height: 480px; ">
<img style="position: absolute; width: 640px; height: 480px; "
src="http://img41.imageshack.us/img41/3221/metropolis04.jpg" >
</div>
</div>
<div id="capa1" style="display: none">
<v:oval style="position: absolute; width: 100px; height: 100px;
background-color: transparent; " id="spot" fillcolor="white"
stroke="true" strokecolor="transparent" strokeweight="0" />
</div>
<p style="font-size: 110%; color:yellow">El efecto está hecho con dos
capas modificadas con el filtro <code>compositor</code> que resta el
color de la <code>capa0</code> al de la <code>capa1</code>. En este
caso hay que usar el código de color inverso al que queremos ver. <br>
Así, para mostrar el <code style=color:#00ff00>lime</code> restamos el
<code style=color:#ff00ff>fuchsia</code>, y para ver el
<code style=color:#ff3333>red</code> (claro) restamos el
<code style="color:#005151; background:white">aqua</code> (oscuro). <br>
El círculo está hecho con <code>VML</code>.</p>
</body>
</html>
Por supuesto, para "iluminar" de verde hay que restar el azul y el rojo del blanco
Código:
R G B
255 255 255 blanco
- 255 0 255 fuchsia
———————————————————
0 255 0 verde
Y la misma operación para el rojo.
Sí. Obvio. Al negro (
0,0,0) no se le puede restar nada.
Solamente cambiamos el problema de lugar.
¿Y ahora de qué nos disfrazamos?
Resulta que hay un modo de "colorear" que no suma ni resta colores, sino que los mezcla. Al superponer dos capas el navegador toma cada pixel de la capa delantera y promedia su color con el del pixel que está detrás en las mismas coordenadas. El efecto crea una ilusión de transparencia, que a estas alturas ya conocemos todos.
Código:
<html xmlns:v="urn:schemas-microsoft-com:vml">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>DESTACADO CON OPACIDAD.</title>
<style type=text/css>
v\:* {behavior: url(#default#VML); }
body {font-size: 100%; background: black; color: red;
font-weight: bold; }
</style>
<script type=text/javascript>
var cursor, destino, titulo, visibilidad, X, Y;
function mueve(evento){
var alfa = document.getElementById("caja");
var bravo = document.getElementById("spotVML");
var charly = document.getElementById("spotCanvas");
var distX = document.getElementById("caja").offsetLeft;
var distY = document.getElementById("caja").offsetTop;
document.title = X+" "+Y+" "+distX+" "+distY;X = (evento.pageX) ? evento.pageX - distX : evento.x ;
Y = (evento.pageY) ? evento.pageY - distY : evento.y ;
if ((X>380 && Y>20) && (X<480 && Y<170)) /*coordenadas calavera*/ {
cursor = "pointer";
destino = "http://imageshack.us/photo/my-images/593/hddm01.jpg";
titulo = "Huesuda.";
visibilidad = "visible";
}
else {
cursor = "alias";
destino =
"http://img710.imageshack.us/slideshow/webplayer.php?id=antoniosegui.jpg";
titulo = "A Colección.";
visibilidad = "hidden";
}
alfa.style.cursor = cursor;
alfa.title = titulo;
bravo.style.visibility =
charly.style.visibility = visibilidad;
}
function lleva(){
window.location = destino;
}
function dibujaEstrella() {
var canvas = document.getElementById("spotCanvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgba(255,195,0,.3)";
ctx.translate(100,100);
ctx.save();
ctx.beginPath();
ctx.moveTo(100,0);
for (i=0;i<9;i++){
ctx.rotate(Math.PI/5);
if(i%2 == 0) {
ctx.lineTo((100/0.425731)*0.200811,0);
}
else {
ctx.lineTo(100,0);
}
}
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
onload = dibujaEstrella;
</script>
</head>
<BODY>
<h1>Destaca una parte de la imagen que tiene el área activa
agregando una capa semitransparente. </h1>
<center><div style="width: 608px; height: 464px; position: relative;
m/argin: auto; overflow: hidden; background-image:
url(http://img593.imageshack.us/img593/4725/hddm01.jpg); "
onclick="lleva()" onmousemove="mueve(event)" id="caja">
<v:shape style="position: absolute; width: 100px; height: 100px;
background-color: transparent; visibility: hidden;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=30);
top:40px; left: 185px; " id="spotVML" fillcolor="#ffc300"
stroke="true" strokecolor="#ffc300" strokeweight="0"
coordorigin="-110 50" coordsize="90,90" path="m 8,65
l 65,54, 92,11, 121,56, 174,65, 130,100, 142,155, 92,131, 42,155, 50,100 x e" />
<canvas id="spotCanvas" width="200" height="200"
style="position: absolute; top: -45px; left: 135px; visibility: hidden;"></canvas>
</div></center>
<p style="font-size: 110%; color:yellow">
La estrella está hecha con <code>VML</code> para <strong>Internet
Explorer</strong> y con <code>canvas</code> para los demás
navegadores. </p>
<p style="color: black; background-color: white;">Homenaje a
"<u><em>Hasta después de muerta</em></u>" (1916, Ernesto Gunche /
Eduardo Martinez de la Pera / Florencio Parravicini).</p>
</body>
</html>
Un par de consideraciones sobre este ejemplo.
El destacado semitransparente no siempre queda bien; de hecho, esa foto lo prueba, pero me quedé sin imágenes de
Metrópolis y ya era hora de que homenajeara un poco al cine argentino.
Las estrellas no son iguales, la de
VML la escribí a mano, para mostrar cómo se arma el
path. Y encima es medio complicado porque ni siquiera usa pixeles, tiene una medida relativa que se declara dentro del código. Muy raro.
Para cuando hice la estrella
canvas, ya tenía las paciencias por el piso y terminé copiando algún código pre-hecho. Total, la idea ya se entendió : le podemos dar cualquier forma. El drama es que ese escript no toma el punto de inicio arriba sino a la derecha, y de allí empieza a rotar las coordenadas; por eso quedó torcida. Y no la voy a arreglar.
De cualquier forma, todos sabemos que en PHP se pueden generar archivos de imagen a partir de coordenadas. Si cargamos en el servidor todos los "recortes" que necesitamos, el navegador los baja ya hechos y los usa como capa. Y nos ahorramos tanto problema de compatibilidad.
Justamente, el último ejemplo es más compatible y ya no tiene el circo de la capa siguiendo al puntero. Con ubicar las imágenes ocultas en su sitio, las podemos "aparecer" con un
hover o un
mouseover en un mapeado.
Y sí, tambien podemos usar
globalCompositeOperation o
DXImageTransform.Microsoft.Compositor() con otros efectos, para destacar con la misma imagen descargada, en vez de generada.
Un problema que adelanto para quien vea este tema dentro de algunos años, es que no preví que MS incorporara
canvas. Para que ese día no termine mostrando juntas las dos capas del código precedente, habrá que poner algún condicional que use uno o el otro método. Y más tarde borrar el de
Internet Explorer.