2012-04-09 66 views
8

有没有办法像使用HTML5/CSS/JavaScript一样在Flash/ActionScript中更改图像的颜色?画布 - 使用HTML5/CSS/JS更改图像的颜色?

下面是Flash中的一个例子:http://www.kirupa.com/developer/actionscript/color.htm编辑:这是我想要复制的过程。

我试图完成这样的(颜色变化方面,保持光照和阴影):http://www.acura.com/ExteriorColor.aspx?model=TL无需加载&每次更换一个新的形象;我希望能够简单地改变色调(即做一个纯粹的HTML5/CSS/JS方法)。 编辑:这是我希望实现的结果,而不是过程。

基本上我想改变图像的调色板/色调,同时保留图像的其他方面(如渐变,照明等)。我已经接近了,但还不够接近;我已经到了在原始图像上使用图像蒙版和复合图像的地步(有点像透明图像叠加)。下面是一些示例代码(请注意,这只是一个片段,因此它可能会或可能无法正常工作;我只是显示的示例代码,所以你得到什么,我试图做一个想法):

<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> 

使用这种方法的主要问题是图像看起来非常平坦。还有其他东西丢失了,或者我使用的遮罩(这是一个坚实的白色不规则形状的图像),是错误的方法。

+0

一旦你有答案,请发表一个完整的小提琴。谢谢! – iambriansreed 2012-04-09 16:44:37

回答

-1

通常做一些像像素一样的像素是你在服务器端做的事情,因为它对浏览器来说非常重。在Acura网站的情况下,没有任何棘手的事情发生 - 他们只是有一堆不同的JPG。您也可以尝试查看Processing.js。

+0

我没有绘制任何像素的像素;我在现有的图像上合成图像蒙版,比每次查询后端要做更多的颜色更快。讴歌正在做的是我想要达到的结果,但不是过程。 Flash可以很好地改变颜色/色调(非常直观),但可悲的现实是,您无法在iPad上使用Flash,这就是我寻找HTML5解决方案的原因。 – 2012-04-09 16:25:58

2

当然,你可以得到像素数据,并对其进行HSV调整。你想要的方法是getImageData(它返回一个UInt8Array,而不是一个普通的js数组)。

有一个很好的写作here这应该让你开始。您可以将透明画布元素叠放在彼此的顶部,这应该有助于避免调整基础组件(以您的汽车为例,轮胎,窗户等)的问题。

11

此功能要求要加载的图像和它必须是来自同一个域(由于跨域策略)

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(); 
} 

假设您的标记看起来是这样的:

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

你可以通过调用以下参数来使用它:

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

工作示例:http://jsfiddle.net/pHwmL/1/

+1

请注意,当您说跨域时,使用chrome进行本地开发的用户将无法看到这一功能(我总是在本地直通网络服务器上运行以验证它是否可行)。我喜欢你的方法,但发现它覆盖了任何alpha通道......所以我添加了一个alpha数组,然后在之后将它们写回。效果很好。代码:https://github.com/jaycrossler/django-gamification/blob/master/gamification/static/themes/camping/badges.js#L711-L733 – JayCrossler 2014-07-24 20:33:37