2012-04-09 19 views
8

¿Hay alguna manera de cambiar los colores de una imagen como en Flash/ActionScript con solo usar HTML5/CSS/JavaScript?Lienzo - ¿Cambiar colores de una imagen usando HTML5/CSS/JS?

Aquí hay un ejemplo en Flash: http://www.kirupa.com/developer/actionscript/color.htmEDITAR: Este es el proceso que deseo duplicar.

que estoy tratando de lograr algo como esto (el cambio de color aspecto, la preservación de iluminación y sombras): http://www.acura.com/ExteriorColor.aspx?model=TL sin cargar & sustituyendo una nueva imagen cada vez; Quiero poder simplemente cambiar el tono de color (es decir, hacer un método puro de HTML5/CSS/JS). EDITAR: Este es el resultado que deseo lograr, no el proceso.

Básicamente quiero cambiar la paleta/tono de una imagen, conservando los otros aspectos de la imagen (como degradado, iluminación, etc.). Me he acercado, pero no lo suficientemente cerca; He llegado al punto en que uso una máscara de imagen y un compuesto que sobre la imagen original (algo así como una superposición de imagen transparente). A continuación se muestra un código de ejemplo (tenga en cuenta que esto es sólo un fragmento, por lo que puede o no puede trabajar, yo sólo estoy mostrando código de ejemplo para que pueda obtener una idea de lo que estoy tratando de hacer):

<div id='mask'> 
    <canvas id='canvas' width='100' height='100'></canvas> 
</div> 
<button data-rgba='255,0,0,0.5'>red</button> 
<button data-rgba='0,255,0,0.5'>green</button> 

<script> 
foo = {}; 
foo.ctx = jQuery('#canvas')[0]; 
foo.ctx_context = foo.ctx.getContext('2d'); 
foo.mask = jQuery('#mask')[0]; 
foo.img = new Image(); 
foo.img_path = '/path/to/image_mask.png'; // 100px x 100px image 

foo.changeColor = function(rgba){ 
    foo.ctx_context.clearRect(0, 0, 100, 100); 
    foo.ctx_context.fillStyle = 'rgba(' + rgba + ')'; 
    foo.ctx_context.fillRect(0, 0, 100, 100); 
    foo.ctx_context.globalCompositeOperation = 'destination-atop'; 
    foo.ctx_context.drawImage(foo.img, 0, 0); 
    foo.ctx_context.css({'background-image': "url(" + foo.ctx.toDataURL("image/png") + ")"}); 
}; 

jQuery("button").click(function(){ 
    foo.changeColor(jQuery(this).attr('data-rgba')); 
}); 
</script> 

El principal problema con el uso de este enfoque es que las imágenes se ven realmente planas. Falta algo más, o la máscara que estoy usando (que es una imagen de forma irregular blanca y sólida) es el enfoque equivocado.

+0

Por favor, publique un violín completo una vez que tenga su respuesta. ¡Gracias! – iambriansreed

Respuesta

-1

Normalmente, hacer algo así como cambiar una imagen píxel por píxel es algo que haría en el lado del servidor, ya que es muy pesado para el navegador. En el caso del sitio web de Acura no pasa nada complicado, solo tienen un montón de JPG diferentes. También puedes intentar investigar en Processing.js.

+0

no dibujo nada píxel por píxel; Estoy componiendo una máscara de imagen sobre una imagen existente, que es MUCHO más rápido que consultar al back-end cada vez para hacer un cambio de color. Lo que Acura está haciendo es el resultado que quiero lograr, pero NO el proceso. El flash cambia de color/tonos tan bien (es inmediato), pero la triste realidad es que no se puede usar Flash en el iPad, por lo que estoy buscando una solución HTML5. –

2

Claro, puede obtener los datos de píxeles y hacer ajustes de HSV en él. El método que desea es getImageData (que devuelve un UInt8Array, no una matriz js normal).

Hay un bonito escrito here que debería comenzar. Puede superponer elementos de lienzo transparentes uno encima del otro, lo que debería ayudar a evitar problemas al ajustar los componentes de la base (en el ejemplo de su automóvil, los neumáticos, las ventanas, etc.).

11

Esta función requiere que la imagen a ser cargada y tiene que ser del mismo dominio (debido a la política entre dominios)

function tintImage(imgElement,tintColor) { 
    // create hidden canvas (using image dimensions) 
    var canvas = document.createElement("canvas"); 
    canvas.width = imgElement.offsetWidth; 
    canvas.height = imgElement.offsetHeight; 

    var ctx = canvas.getContext("2d"); 
    ctx.drawImage(imgElement,0,0); 

    var map = ctx.getImageData(0,0,320,240); 
    var imdata = map.data; 

    // convert image to grayscale 
    var r,g,b,avg; 
    for(var p = 0, len = imdata.length; p < len; p+=4) { 
     r = imdata[p] 
     g = imdata[p+1]; 
     b = imdata[p+2]; 
     // alpha channel (p+3) is ignored   

     avg = Math.floor((r+g+b)/3); 

     imdata[p] = imdata[p+1] = imdata[p+2] = avg; 
    } 

    ctx.putImageData(map,0,0); 

    // overlay filled rectangle using lighter composition 
    ctx.globalCompositeOperation = "lighter"; 
    ctx.globalAlpha = 0.5; 
    ctx.fillStyle=tintColor; 
    ctx.fillRect(0,0,canvas.width,canvas.height); 

    // replace image source with canvas data 
    imgElement.src = canvas.toDataURL(); 
} 

Asumiendo que su margen de beneficio se ve así:

<img id='myimage' src='image.jpg'/> 

Usted podría usarlo llamándolo con los siguientes parámetros:

tintImage(
    document.getElementById('myImage'), 
    "#550000" // for a redish tint 
); 

Ejemplo de trabajo aquí: http://jsfiddle.net/pHwmL/1/

+1

Tenga en cuenta que cuando diga dominio cruzado, las personas que usen chrome para desarrollar localmente no podrán ver esto funcionando bien (siempre corro en un servidor web de paso a través local para verificar que funcione). Me gustó su método , pero descubrí que sobreescribía cualquier canal alfa ... así que agregué una matriz de alfas y luego las escribí de nuevo. Funciona bien. Código en: https://github.com/jaycrossler/django-gamification/blob/master/gamification/static/themes/camping/badges.js#L711-L733 – JayCrossler

Cuestiones relacionadas