【问题标题】:Why is my canvas fill pattern repeating/overlapping itself?为什么我的画布填充图案会重复/重叠?
【发布时间】:2012-07-13 11:27:58
【问题描述】:

我绘制了一个圆角矩形网格,我需要用图像背景填充它们。最终我会有很多图像背景,但现在,我正试图让它与一个一起工作。我很接近,我的矩形绘制但填充有点奇怪 - 它自身重叠并杀死我的图案(边缘除外)基本上用图像填充整个画布。我试图“剪裁”我的路径,但这只会导致填充一个矩形。我不确定我做错了什么,我希望画布专家能发现它?

/* 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);       

                }
             }
};

【问题讨论】:

    标签: javascript html5-canvas


    【解决方案1】:

    假设您的问题在此 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/

    关于我所做的其他小调整的一些说明:

    • 确保你总是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 进行调试通常要容易得多。 (打开开发者控制台查看输出。)

    • 我在列计算中添加了灌浆的最后外行/列,以确保有空间可以包含它。使用或不使用。

    【讨论】:

    • 你太棒了,我不知道该说什么,除了非常衷心的感谢。我很欣赏为解决这个问题而做出的特别回应。被吃掉的开始路径很蹩脚,需要检查我的眼睛!
    猜你喜欢
    • 2011-10-24
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 2016-08-11
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多