如何使用HTML5画布为图像着色?

如何使用HTML5画布为图像着色?,html,canvas,2d,Html,Canvas,2d,我的问题是,对使用drawImage方法绘制的图像着色的最佳方法是什么。这项技术的目标用途是高级2d粒子效果(游戏开发),其中粒子会随着时间的推移而改变颜色等。我不是问如何给整个画布着色,而是问我将要绘制的当前图像 我的结论是globalAlpha参数会影响当前绘制的图像 //works with drawImage() canvas2d.globalAlpha = 0.5; 但是如何使用任意颜色值为每个图像着色?如果有某种globalFillStyle或globalColor之类的东西,那就

我的问题是,对使用drawImage方法绘制的图像着色的最佳方法是什么。这项技术的目标用途是高级2d粒子效果(游戏开发),其中粒子会随着时间的推移而改变颜色等。我不是问如何给整个画布着色,而是问我将要绘制的当前图像

我的结论是globalAlpha参数会影响当前绘制的图像

//works with drawImage()
canvas2d.globalAlpha = 0.5;
但是如何使用任意颜色值为每个图像着色?如果有某种globalFillStyle或globalColor之类的东西,那就太棒了

编辑:

以下是我正在使用的应用程序的屏幕截图:

当我创建粒子测试时,我只是基于旋转(如35次旋转)、色彩和alpha缓存图像,并创建一个包装器,以便自动创建它们。效果很好。是的,应该有某种着色操作,但在处理软件渲染时,最好的选择是缓存所有内容,就像在flash中一样。


颗粒试验
函数粒子(x,y)
{
这个位置=新向量(x,y);
这个速度=新矢量(0.0,0.0);
该力=新矢量(0.0,0.0);
这个质量=1;
这个α=0;
}
//帆布
var=null;
var context2D=null;
//蓝色粒子纹理
var blueparticlexture=新图像();
var blueparticlextureload=false;
var blueparticlexturealpha=新数组();
var mousePosition=新向量();
var mouseDownPosition=新向量();
//粒子
var particles=新数组();
var中心=新向量(250250);
var图像数据;
函数初始化()
{
canvas=document.getElementById('canvas');
context2D=canvas.getContext('2d');
对于(var createEntity=0;createEntity<150;++createEntity)
{
var randomAngle=Math.random()*Math.PI*2;
var粒子=新粒子(数学cos(随机角度)*250+250,数学sin(随机角度)*250+250);
particle.velocity=center.Subtract(particle.position).Normal().Normalize().Multiply(Math.random()*5+2);
particle.mass=Math.random()*3+0.5;
粒子。推(粒子);
}
blueParticleTexture.onload=函数()
{
drawImage(blueParticleTexture,0,0);
imageData=context2D.getImageData(0,0,5,5);
var imageDataPixels=imageData.data;

对于(var i=0;i这个问题仍然存在。一些人似乎建议的解决方案是将要着色的图像绘制到另一个画布上,然后从那里抓取ImageData对象,以便能够逐像素修改它,问题是在游戏开发环境中,它实际上是不可接受的,因为我基本上必须绘制每个粒子2次而不是1次。我将尝试的一个解决方案是在实际应用程序开始之前,在画布上绘制每个粒子一次并抓取ImageData对象,然后使用ImageData对象而不是实际的图像对象,但创建新副本可能会有点昂贵,因为我必须保留未修改的副本d每个图形的原始ImageData对象。

您有合成操作,其中一个是destination Top。如果使用“context.globalCompositeOperation=”destination Top”将图像合成到纯色上,它将有前景图像的alpha和背景图像的颜色。我用它制作了一个图像的完全着色副本,然后在原稿的顶部绘制了一个完全着色的副本,不透明度等于我想要着色的数量

以下是完整的代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>HTML5 Canvas Test</title>
        <script type="text/javascript">
var x; //drawing context
var width;
var height;
var fg;
var buffer

window.onload = function() {
    var drawingCanvas = document.getElementById('myDrawing');
    // Check the element is in the DOM and the browser supports canvas
    if(drawingCanvas && drawingCanvas.getContext) {
        // Initaliase a 2-dimensional drawing context
        x = drawingCanvas.getContext('2d');
        width = x.canvas.width;
        height = x.canvas.height;

        // grey box grid for transparency testing
        x.fillStyle = '#666666';
        x.fillRect(0,0,width,height);
        x.fillStyle = '#AAAAAA';
        var i,j;
        for (i=0; i<100; i++){
            for (j=0; j<100; j++){
                if ((i+j)%2==0){
                    x.fillRect(20*i,20*j,20,20);
                }
            }
        }

        fg = new Image();
        fg.src = 'http://uncc.ath.cx/LayerCake/images/16/3.png';

        // create offscreen buffer, 
        buffer = document.createElement('canvas');
        buffer.width = fg.width;
        buffer.height = fg.height;
        bx = buffer.getContext('2d');

        // fill offscreen buffer with the tint color
        bx.fillStyle = '#FF0000'
        bx.fillRect(0,0,buffer.width,buffer.height);

        // destination atop makes a result with an alpha channel identical to fg, but with all pixels retaining their original color *as far as I can tell*
        bx.globalCompositeOperation = "destination-atop";
        bx.drawImage(fg,0,0);


        // to tint the image, draw it first
        x.drawImage(fg,0,0);

        //then set the global alpha to the amound that you want to tint it, and draw the buffer directly on top of it.
        x.globalAlpha = 0.5;
        x.drawImage(buffer,0,0);
    }
}
        </script>
    </head>
    </body>
        <canvas id="myDrawing" width="770" height="400">
            <p>Your browser doesn't support canvas.</p>
        </canvas>
    </body>
</html>

HTML5画布测试
var x;//绘图上下文
var宽度;
变异高度;
var-fg;
变量缓冲区
window.onload=函数(){
var drawingCanvas=document.getElementById('myDrawing');
//检查元素是否在DOM中,并且浏览器是否支持画布
if(drawingCanvas&&drawingCanvas.getContext){
//初始化二维图形上下文的别名
x=drawingCanvas.getContext('2d');
宽度=x.canvas.width;
高度=x.canvas.height;
//用于透明度测试的灰盒网格
x、 fillStyle='#666666';
x、 fillRect(0,0,宽度,高度);
x、 fillStyle='#aaaaa';
varⅠ,j;

对于(i=0;i我想看看这个:他似乎有一种颜色变换方法,我相信他正在绘制一个形状来进行变换,但也许基于此,你可以找到一种调整特定图像的方法。

有一种方法可以用来给图像着色,它比绘制彩色矩形更精确,比处理pixe更快在那篇博客文章中有完整的解释,包括JS代码,但这里是它工作原理的总结

首先,你要逐个像素地对图像着色,读取数据,并将每个像素分成4个独立的组件:红色、绿色、蓝色和黑色。你要将每个组件写入一个单独的画布。因此,现在你有了原始图像的4个(红色、绿色、蓝色和黑色)版本

当您想要绘制着色图像时,您可以创建(或找到)屏幕外画布并将这些组件绘制到其中。首先绘制黑色,然后需要将画布的globalCompositeOperation设置为“lighter”,以便将下一个组件添加到画布中。黑色也是不透明的

接下来将绘制三个组件(红色、蓝色和绿色图像),但它们的alpha值取决于它们的组件构成绘图颜色的多少。因此,如果颜色为白色,则所有三个都用1个alpha绘制。如果颜色为绿色,则仅绘制绿色图像,跳过其他两个。如果颜色为橙色,则红色上有完整的alpha,绘制绿色部分透明并跳过蓝色的

现在,您已经在备用画布上渲染了图像的着色版本,您只需将其绘制到画布上任何需要的位置

同样,在博客文章中也有这样做的代码。

<
// Vector class

// TODO: EXamples
// v0 = v1 * 100 + v3 * 200; 
// v0 = v1.MultiplY(100).Add(v2.MultiplY(200));

// TODO: In the future maYbe implement:
// VectorEval("%1 = %2 * %3 + %4 * %5", v0, v1, 100, v2, 200);

function Vector(X, Y)
{
    /*
    this.__defineGetter__("X", function() { return this.X; });
    this.__defineSetter__("X", function(value) { this.X = value });

    this.__defineGetter__("Y", function() { return this.Y; });
    this.__defineSetter__("Y", function(value) { this.Y = value });
    */

    this.Add = function(v)
    {
        return new Vector(this.X + v.X, this.Y + v.Y);
    }

    this.Subtract = function(v)
    {
        return new Vector(this.X - v.X, this.Y - v.Y);
    }

    this.Multiply = function(s)
    {
        return new Vector(this.X * s, this.Y * s);
    }

    this.Divide = function(s)
    {
        return new Vector(this.X / s, this.Y / s);
    }

    this.ThisAdd = function(v)
    {
        this.X += v.X;
        this.Y += v.Y;
        return this;
    }

    this.ThisSubtract = function(v)
    {
        this.X -= v.X;
        this.Y -= v.Y;
        return this;
    }

    this.ThisMultiply = function(s)
    {
        this.X *= s;
        this.Y *= s;
        return this;
    }

    this.ThisDivide = function(s)
    {
        this.X /= s;
        this.Y /= s;
        return this;
    }

    this.Length = function()
    {
        return Math.sqrt(this.X * this.X + this.Y * this.Y);
    }

    this.LengthSquared = function()
    {
        return this.X * this.X + this.Y * this.Y;
    }

    this.Normal = function()
    {
        return new Vector(-this.Y, this.X);
    }

    this.ThisNormal = function()
    {
        var X = this.X;
        this.X = -this.Y
        this.Y = X;
        return this;
    }

    this.Normalize = function()
    {
        var length = this.Length();
        if(length != 0)
        {
            return new Vector(this.X / length, this.Y / length);
        }
    }

    this.ThisNormalize = function()
    {
        var length = this.Length();
        if (length != 0)
        {
            this.X /= length;
            this.Y /= length;
        }
        return this;
    }

    this.Negate = function()
    {
        return new Vector(-this.X, -this.Y);
    }

    this.ThisNegate = function()
    {
        this.X = -this.X;
        this.Y = -this.Y;
        return this;
    }

    this.Compare = function(v)
    {
        return Math.abs(this.X - v.X) < 0.0001 && Math.abs(this.Y - v.Y) < 0.0001;
    }

    this.Dot = function(v)
    {
        return this.X * v.X + this.Y * v.Y;
    }

    this.Cross = function(v)
    {
        return this.X * v.Y - this.Y * v.X;
    }

    this.Projection = function(v)
    {
        return this.MultiplY(v, (this.X * v.X + this.Y * v.Y) / (v.X * v.X + v.Y * v.Y));
    }

    this.ThisProjection = function(v)
    {
        var temp = (this.X * v.X + this.Y * v.Y) / (v.X * v.X + v.Y * v.Y);
        this.X = v.X * temp;
        this.Y = v.Y * temp;
        return this;
    }

    // If X and Y aren't supplied, default them to zero
    if (X == undefined) this.X = 0; else this.X = X;
    if (Y == undefined) this.Y = 0; else this.Y = Y;
}
/*
Object.definePropertY(Vector, "X", {get : function(){ return X; },
                               set : function(value){ X = value; },
                               enumerable : true,
                               configurable : true});
Object.definePropertY(Vector, "Y", {get : function(){ return X; },
                               set : function(value){ X = value; },
                               enumerable : true,
                               configurable : true});
*/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>HTML5 Canvas Test</title>
        <script type="text/javascript">
var x; //drawing context
var width;
var height;
var fg;
var buffer

window.onload = function() {
    var drawingCanvas = document.getElementById('myDrawing');
    // Check the element is in the DOM and the browser supports canvas
    if(drawingCanvas && drawingCanvas.getContext) {
        // Initaliase a 2-dimensional drawing context
        x = drawingCanvas.getContext('2d');
        width = x.canvas.width;
        height = x.canvas.height;

        // grey box grid for transparency testing
        x.fillStyle = '#666666';
        x.fillRect(0,0,width,height);
        x.fillStyle = '#AAAAAA';
        var i,j;
        for (i=0; i<100; i++){
            for (j=0; j<100; j++){
                if ((i+j)%2==0){
                    x.fillRect(20*i,20*j,20,20);
                }
            }
        }

        fg = new Image();
        fg.src = 'http://uncc.ath.cx/LayerCake/images/16/3.png';

        // create offscreen buffer, 
        buffer = document.createElement('canvas');
        buffer.width = fg.width;
        buffer.height = fg.height;
        bx = buffer.getContext('2d');

        // fill offscreen buffer with the tint color
        bx.fillStyle = '#FF0000'
        bx.fillRect(0,0,buffer.width,buffer.height);

        // destination atop makes a result with an alpha channel identical to fg, but with all pixels retaining their original color *as far as I can tell*
        bx.globalCompositeOperation = "destination-atop";
        bx.drawImage(fg,0,0);


        // to tint the image, draw it first
        x.drawImage(fg,0,0);

        //then set the global alpha to the amound that you want to tint it, and draw the buffer directly on top of it.
        x.globalAlpha = 0.5;
        x.drawImage(buffer,0,0);
    }
}
        </script>
    </head>
    </body>
        <canvas id="myDrawing" width="770" height="400">
            <p>Your browser doesn't support canvas.</p>
        </canvas>
    </body>
</html>