Ver Mensaje Individual
  #18 (permalink)  
Antiguo 21/12/2011, 06:55
furoya
(Desactivado)
 
Fecha de Ingreso: noviembre-2002
Ubicación: Ciudad Autónoma de Buenos Aires
Mensajes: 2.367
Antigüedad: 21 años, 5 meses
Puntos: 317
Respuesta: Aplicar filtro o similar sobre un elemento SHAPE de una imagen

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.