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

Si ya vieron el código funcionando, habrán notado que el "rendering" del filtro cromaK es un poco costoso para máquinas no muy potentes. Eso ralentiza el seguimiento del VML al cursor.
Una forma de evitarlo es replantear todo el efecto, y usar sólo Vectorial MarkUp Language; algo como usar sólo canvas. Pero me desanimé cuando el atributo

cromakey="blue"

no funcionó. Supongo que habré hecho algo mal, pero ya no estoy para ponerme a hacer experimentos con un lenguaje del que hay poca bibliografía. La misma gente de Microsoft ya dejó de actualizarlo y liquidó los editores que tenía para descargar.

Entonces recordé el filtro

-ms-filter: progid:DXImageTransform.Microsoft.Compositor(funct ion=??, duration=??);

que —justamente— tiene una función XOR.

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 10 Y Light.</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 colorea() {
/*aplica el efecto de color rojo a 'capaFondo'*/
document.getElementById("capaFondo").filters.item
("DXImageTransform.Microsoft.Light").addAmbient(255, 150, 150, 100);
}
 
function mueve(evento){
var alfa = document.getElementById("caja");
var bravo = document.getElementById("spot");
var charly = document.getElementById("capaFondo");
 
X = evento.x ;
Y = evento.y ;
 
if ((X>255 && Y>160) && (X<320 && Y<210)) /*coordenadas cabeza*/ { 
cursor = "pointer";
destino = "http://img35.imageshack.us/i/metropolis02.jpg"; 
titulo = "Cabeza.";
/*cambia color de 'capaFondo' a verde*/
charly.filters.item
("DXImageTransform.Microsoft.Light").changeColor(0, 0,255,0, 1);
}
 
else {
cursor = "move";
destino = 
"http://img710.imageshack.us/slideshow/webplayer.php?id=antoniosegui.jpg";
titulo = "A Colección.";
/*cambia color de 'capaFondo' a rojo claro*/
charly.filters.item
("DXImageTransform.Microsoft.Light").changeColor(0, 255,150,150, 1);
}
 
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">

<img style="position: absolute; width:640px; height:480px; 
-ms-filter: 
progid:DXImageTransform.Microsoft.Light(enabled=true);
filter: progid:DXImageTransform.Microsoft.Light(enabled=true);" 
src="http://img35.imageshack.us/img35/7231/metropolis02.jpg" 
onload="colorea()" id="capaFondo">

<div id="capa0" 
style="-ms-filter: 
progid:DXImageTransform.Microsoft.Compositor(function=10, duration=10); 
filter: 
progid:DXImageTransform.Microsoft.Compositor(function=10, duration=10); 
position: absolute; top: 0; left: 0; width: 640px; height: 480px; ">
<img style="width:640px; height:480px; "
src="http://img35.imageshack.us/img35/7231/metropolis02.jpg" >
</div>

</div>

<div id="capa1" style="display: none">
<v:oval style="position: absolute; width:100px; height:100px; 
background-color: transparent;" id="spot" fillcolor="red"
stroke="true" strokecolor="transparent" strokeweight="0" />
</div>

<p style="font-size: 110%">El efecto está hecho con dos capas 
modificadas con el filtro <code>compositor</code> que borra de la 
<code>capa0</code> el dibujo de la <code>capa1</code>. Una tercera 
capa (<code>capaFondo</code>) tiene aplicado un filtro <code>light
</code> que la vira al verde o al rojo según el puntero se encuentre 
o no en el área activa, y es la que se ve a través del círculo. <br>
El círculo está hecho con <code>VML</code>. </p>
</body>
</html>
Este filtro no es de mis preferidos. La única forma que encontré de hacerlo andar es aplicarlo a una capa y después agregar la segunda vía javascript. Pero como los ajustes de light y la animación ya usaban JS, en este caso no es muy grave.
Salvo por el detalle de que todavía se mueve lento.
Y está claro: está usando el mismo DX que chroma.

Como el asunto ya se estaba haciendo 'personal', empecé a probar otras alternativas. Y encontré dos que podrían servir en el mismo compositor.

Resulta que también nos da la posibilidad de sumar colores entre capas. Quiero decir, que si una tiene un círculo rojo, y la pongo sobre otra que es una fotografía, justo donde le falte el componente "R" en el "RGB" le va a sumar el del círculo. Y eso se parece mucho a un efecto de iluminación.

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 9.</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 = "#00ff00";
}
 
else {
cursor = "move";
destino = 
"http://img710.imageshack.us/slideshow/webplayer.php?id=antoniosegui.jpg";
titulo = "A Colección.";
bravo.fillcolor = "#ff3333";
}

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=9, duration=9); 
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="#ff3333"
stroke="true" strokecolor="transparent" strokeweight="0" />
</div>

<p style="font-size: 110%">El efecto está hecho con dos capas 
modificadas con el filtro <code>compositor</code> que suma el color 
de la <code>capa0</code> al de la <code>capa1</code>.<br>
El círculo está hecho con <code>VML</code>.</p>
</body>
</html>
Pero —siempre hay un 'pero'— en las partes que tienen un "rojo más alto", como en el blanco que tiene 255,255,255, no se va a notar el cambio. Y como justo en nuestro ejemplo El Ñato está dibujado con blanco, el efecto medio que se pierde. ¿No?.