画布意外的结果/行为使用drawImage / putImageData

时间:2013-03-23 08:40:03

标签: javascript canvas

在尝试获取画布的绘图并将其重新绘制到同一画布上之后会产生意外行为。例如,请参阅 Jsfiddle

逻辑非常简单:

  • 在画布上给出一个图像,并转换到中心(我使用矩形来演示)。
  • 剪切图像的一部分。我只是在示例中复制整个“图像”。
  • 可能会进行操纵。
  • 清除后粘贴回同一画布。要点是在宽度/高度的给定点处剪切原始图像的一部分,稍后将其粘贴并进行修改。

var c=document.getElementById("cvs1"),
    ctx = c.getContext("2d"),
    bufferCvs = document.createElement('canvas'),
    bufferCtx = bufferCvs.getContext('2d');


bufferCvs.width = c.width;
bufferCvs.height = c.height;

ctx.translate( c.width/2, c.height/2 );
ctx.fillStyle="#FF0000";
ctx.fillRect( -75, -50 ,150,100);

//Image data experiment
//Set the buffer width / height same size as rectangle
bufferCvs.width = 150;
bufferCvs.height = 100;
//Draw the "image" from the first context to the buffer by clipping the first, and pasting to 0,0 width the same "image" dimensions.
bufferCtx.drawImage( c, -75, -50, 150, 100, 0, 0, 150, 100 );
//clear out old canvas drawing
ctx.save()
ctx.setTransform(1,0,0,1,0,0,1,0,0);
ctx.clearRect(0, 0, c.width, c.height);
ctx.restore();

ctx.drawImage( bufferCvs, -75, -50, 150, 100 );

由于我保持完全相同的坐标/尺寸,因此预期的输出将是最初在画布上开始的。但是,只绘制了左上角的一部分(参见小提琴)。我正在使用drawImage用于 efficiency reasons ,但我使用了get / putImageData,结果相同。宽度和高度都是按照上述方法定义的,用于修复 other strange behaviors

您如何确保绘制存储在缓冲区画布中的所有内容,而不仅仅是顶角?

编辑: 为了解决我的问题以及我认为正在发生的行为,我会发布一些屏幕。

第1步: 将上下文1翻译为中心,并绘制一个矩形来表示图像。

ctx.translate( c.width/2, c.height/2 );
ctx.fillStyle="#FF0000";
ctx.fillRect( -75, -50 ,150,100);

Translate / Add Rect

第2步: 使用drawImage从-75,-50点“剪切”并使用宽度150,100切出矩形。这应该绘制到画布缓冲区,但它不是

bufferCvs.width = 150;
bufferCvs.height = 100;
//Draw the "image" from the first context to the buffer by clipping the first at -75, -50 (the start of the image), and pasting to 0,0 width the same "image" dimensions.
bufferCtx.drawImage( c, -75, -50, 150, 100, 0, 0, 150, 100 );

我希望缓冲画布看起来像这样(它不是):

Expected buffer canvas

但是,如果我将drawImage更改为

bufferCtx.drawImage( c, 0, 0, 150, 100, 0, 0, 150, 100 );

我在缓冲区上获得了预期的空白量(并且最后一个drawImage返回到上下文而没有问题)

步骤3:从第一个上下文中清除旧的“图像”。这不应该改变翻译,因为我在执行clear之后恢复了上下文状态。 (这可以按预期工作)

ctx.save()
ctx.setTransform(1,0,0,1,0,0,1,0,0);
ctx.clearRect(0, 0, c.width, c.height);
ctx.restore();

步骤4:只需获取缓冲区画布中的内容并将其绘制到原始上下文中,它开始返回到此:

Translate / Add Rect

这个想法是更多地“剪辑”原始区域,清除旧图像,并将新剪切区域中心粘贴回原始上下文。我查看了 MDN's example ,但是drawImage的剪切部分没有像我预期的那样执行。

1 个答案:

答案 0 :(得分:0)

主要问题是在bufferCvs上绘制的第一幅画布未在您期望的地方绘制。证明这一点的最简单方法是将bufferCvs添加到DOM树:http://jsfiddle.net/CdWn6/4/

我想这就是你要找的东西:http://jsfiddle.net/CdWn6/6/

var c=document.getElementById("cvs1"),
    c2 = document.getElementById("cvs2"),
    bufferCvs = document.createElement('canvas'),
    bufferCtx = bufferCvs.getContext('2d'),
    ctx = c.getContext("2d"),
    ctx2 = c2.getContext("2d");

bufferCvs.width = c.width;
bufferCvs.height = c.height;

ctx.translate( c.width/2, c.height/2 );
ctx.fillStyle="#FF0000";
ctx2.translate( c.width/2, c.height/2 );
ctx2.fillStyle="#FF0000";

bufferCtx.translate( c.width/2, c.height/2 );

ctx.fillRect( -75, -50 ,150,100);
ctx2.fillRect( -75, -50 ,150,100);

//Image data experiment
bufferCtx.drawImage( c, -135, -110, 270, 220);

ctx.save()
ctx.setTransform(1,0,0,1,0,0,1,0,0);
ctx.clearRect(0, 0, c.width, c.height);
ctx.restore();

//Draw background to demonstrate coordinates still work
ctx.fillStyle="#00FF00";
//ctx.fillRect( -75, -50 ,150,100);

ctx.drawImage( bufferCvs, -75, -50, 150, 100 );