为什么我的画布填充图案重复/重叠?

时间:2012-07-12 21:50:11

标签: javascript html5-canvas

我画了一个圆角矩形网格,我需要用图像背景填充它们。最终我会有很多图像背景,但是现在,我正试图让它与一个人合作。我很接近,我的矩形绘制,但填充做了一些有点蠢事 - 它重叠自己并杀死我的模式(除了在边缘)基本上填充整个画布与图像。我试图'剪辑'我的路径,但这只会导致只填充一个矩形。我不确定我做错了什么,我希望画布专家可以发现它?

/* build rounded rectangle */
var roundedRect=function(ctx,x,y,width,height,radius,fill,stroke) 
{ 

 ctx.save(); // save the context so we don't mess up others ctx.beginPath(); 

// draw top and top right corner ctx.moveTo(x+radius,y);
ctx.arcTo(x+width,y,x+width,y+radius,radius); 

// draw right side and bottom right corner 
ctx.arcTo(x+width,y+height,x+width-radius,y+height,radius); 

// draw bottom and bottom left corner 
ctx.arcTo(x,y+height,x,y+height-radius,radius); 

// draw left and top left corner 
ctx.arcTo(x,y,x+radius,y,radius); 
ctx.clip(); 

if(fill){ ctx.fill(); } 

if(stroke){ ctx.stroke(); } 

 ctx.restore(); // restore context to what it was on entry 
} 

/* onload, fill canvas with pattern of rounded rectangles separated by 2px */
window.onload = function() {
var canvas = document.getElementById("canvas");
/* rounded filled rectangle pattern */
var canvasWidth=530;
    var canvasHeight=530;
    var recWidth=42;
    var recHeight=42;
    var grout=2;
    var radius=2;
    var cols=canvasWidth/(recWidth+grout);
    var rows=canvasWidth/(recHeight+grout);


    /* loop through each row/column to build pattern */
    alert("rows" + rows + " & cols " + cols);
    for (i=1; i<rows; i++){
        for (j=1; j<cols; j++){
            var ctx = canvas.getContext("2d");
            /* fill pattern */
            var img=document.getElementById("poppy");
            var pat=ctx.createPattern(img,"repeat");
            ctx.fillStyle=pat;  
            roundedRect(ctx,(j*grout + (j-1)*recWidth),(i*grout + (i-1)*recHeight),recWidth,recHeight,radius,true,false);       

                }
             }
};

1 个答案:

答案 0 :(得分:2)

让我们假设你的问题在这个JSFiddle中重现:http://jsfiddle.net/hBEwr/。 (如果不是这种情况,那么这个答案的其余部分就是〜bunk;请编辑以符合您的确切问题。)

  1. 如果我们完全从等式中删除模式,我们可以看出它不是直接责怪。
    http://jsfiddle.net/hBEwr/1/
    相反,圆形的管道不会在它们之间留下必要的灌浆。

  2. 由于一切都在相互运行,我们然后将填充颜色更改为低不透明蓝色。有意思!
    http://jsfiddle.net/hBEwr/2/
    我们看到许多路径一次又一次地被吸引。这种洞察力使我们更密切地关注roundedRect()的实施,并注意到我们从不致电beginPath()。实际上,在上面问题的代码中,似乎已经被评论吃掉了。如果没有此调用,roundedRect()的每次调用都会将其他矩形添加到不断增长的路径中,而不是重新开始。

  3. 将呼叫添加到beginPath(),我们看到我们正在走向成功之路:
    http://jsfiddle.net/hBEwr/3/

  4. 现在我们可以添加回模式(略有变化)并取得光荣的胜利:
    http://jsfiddle.net/hBEwr/4/
    Poppies! Poppies! Poppies!

  5. 关于我做的其他小调整的一些注释:

    • 确保始终var您的本地变量:

      for (i=0; i<10; i++)     // Oops! i is a global variable
      for (var i=0; i<10; i++) // Much better
      
    • 重新获取ctximg并为每个磁贴创建模式效率很低。在上面的最终代码中,为了简单和快速,我将它们移到了循环之外。

    • 使用console.log代替alert进行调试通常要容易得多。 (打开开发人员控制台以查看输出。)

    • 我在柱子计算中添加了灌浆的最后一排/ col,以确保有空间包含它。是否随意使用。