2013-08-22 75 views
3

我正嘗試創建一個重疊形狀的數組。但是我很難阻止那些堆疊在一起的形狀。如何使用畫布創建重疊 - 不堆疊 - 形狀?

我想我想讓它們齧合在一起,如果有意義的話?

下面的代碼:

var overlap_canvas = document.getElementById("overlap"); 
var overlap_context = overlap_canvas.getContext("2d"); 
var x = 200; 
var y = x; 
var rectQTY = 4 // Number of rectangles 

overlap_context.translate(x,y); 

for (j=0;j<rectQTY;j++){ // Repeat for the number of rectangles 

// Draw a rectangle 
overlap_context.beginPath(); 
overlap_context.rect(-90, -100, 180, 80); 
overlap_context.fillStyle = 'yellow'; 
overlap_context.fill(); 
overlap_context.lineWidth = 7; 
overlap_context.strokeStyle = 'blue'; 
overlap_context.stroke(); 

// Degrees to rotate for next position 
overlap_context.rotate((Math.PI/180)*360/rectQTY); 
} 

而且這裏是我的jsfiddle: http://jsfiddle.net/Q8yjP/

這裏就是我想要實現:

http://postimg.org/image/iio47kny3/

任何幫助或指導將非常感謝!

回答

7

找什麼你不能指定此行爲,但你可以實現使用複合模式,在算法上下的方式。

正如this demo the result will be like此圖所示:

Squares with overlap

定義線的寬度和你想畫(你可以填補這個數組你已經有計算的位置/角度循環矩形 - 爲簡單起見,我只是在這裏使用硬編碼的):

var lw = 4, 
    rects = [ 
     [20, 15, 200, 75], 
     [150, 20, 75, 200], 
     [20, 150, 200, 75], 
     [15, 20, 75, 200] 
    ], ... 

我將在下面解釋行寬。

/// set line-width to half the size 
ctx.lineWidth = lw * 0.5; 

在循環中爲第一次繪製添加一個標準,這也是您更改複合模式的位置。我們還與最後矩形清除畫布:

/// loop through the array with rectangles 
for(;r = rects[i]; i++) { 
    ctx.beginPath(); 
    ctx.rect(r[0], r[1], r[2], r[3]); 
    ctx.fill(); 
    ctx.stroke(); 

    /// if first we do a clear with last rectangle and 
    /// then change composite mode and line width 
    if (i === 0) { 
     r = rects[rects.length - 1]; 
     ctx.clearRect(r[0] - lw * 0.5, r[1] - lw * 0.5, r[2] + lw, r[3] + lw); 
     ctx.lineWidth = lw; 
     ctx.globalCompositeOperation = 'destination-over'; 
    } 
} 

這將繪製矩形,你必須靈活地改變大小,而不需要重新計算剪裁。

線寬單獨設置爲stroke從中間劃線。因此,由於我們稍後使用destination-over模式,這意味着一半的線將不可見,因爲我們第一次填充它成爲目的地的一部分,因此筆畫將只能夠填充到筆劃區域之外(您可以顛倒stroke的順序和fill,但總是會對第一個矩形進行調整)。

我們還需要它來計算必須包含(一半)外部線條的剪輯。

這也是爲什麼我們最初將其設置爲第一次繪製整條線時的原因 - 否則第一個矩形會有兩倍厚邊框。

+0

和下投票是爲了什麼? – K3N

+0

謝謝。這是一個很大的幫助,非常感謝您的意見。 – Mattarn

1

要做到這一點的唯一方法就是剪切矩形並計算哪一個矩形通過哪一個矩形。但我認爲你將不得不分別繪製你的邊框和內部矩形,因爲分隔矩形會添加額外的邊框。

希望它幫助

1

可悲的是,你要使用的畫布元素的一部分設置的z索引的功能不可用當前。如果你只是需要它的四個矩形對象,你可以做這樣的事情,隱藏矩形的一部分來僞造你想要的效果,但是這被硬編碼爲只有4個矩形。

var overlap_canvas = document.getElementById("overlap"); 
var overlap_context = overlap_canvas.getContext("2d"); 
var x = 200; 
var y = x; 
var rectQTY = 4 // Number of rectangles 

overlap_context.translate(x, y); 

for (j = 0; j < rectQTY; j++) { // Repeat for the number of rectangles 
    // Draw a rectangle 
    overlap_context.beginPath(); 
    overlap_context.rect(-90, -100, 180, 80); 
    overlap_context.fillStyle = 'yellow'; 
    overlap_context.fill(); 
    overlap_context.lineWidth = 7; 
    overlap_context.strokeStyle = 'blue'; 
    overlap_context.stroke(); 
    if (j === 3) { 
     overlap_context.beginPath(); 
     overlap_context.rect(24, -86, 72, 80); 
     overlap_context.fillStyle = 'yellow'; 
     overlap_context.fill(); 
     overlap_context.closePath(); 

     overlap_context.beginPath(); 
     overlap_context.moveTo(20, -89.5); 
     overlap_context.lineTo(100, -89.5); 
     overlap_context.stroke(); 
     overlap_context.closePath(); 

     overlap_context.beginPath(); 
     overlap_context.moveTo(20.5, -93.1); 
     overlap_context.lineTo(20.5, 23); 
     overlap_context.stroke(); 
     overlap_context.closePath(); 
    } 

    // Degrees to rotate for next position 
    overlap_context.rotate((Math.PI/180) * 360/rectQTY); 
} 

Demo here

如果你必須使它的動態,你可以減少像黑暗鴨建議或者你可以嘗試創建,當一個對象被重疊檢測功能,並重繪每一次的形狀矩形(很難做,不知道它是否會工作)。也許你可以拿出一些關於如何讓他們現在硬編碼的元素定位方程,以便總是根據旋轉角度工作,這將是你最好的選擇IMO,但我不知道如何做到這一點正是

總的來說你真的不能做你在這個時間點

+0

感謝您發佈工作的jsfiddle –

0

使用純JavaScript ...

<!DOCTYPE html> 
<html> 
    <head></head> 
    <body> 
     <canvas id="mycanvas" width="400px" height="400px"></canvas> 
     <script> 
      window.onload = function(){ 
       var canvas = document.getElementById('mycanvas'); 
       var ctx = canvas.getContext('2d'); 
       //cheat - use a hidden canvas 
       var hidden = document.createElement('canvas'); 
       hidden.width = 400; 
       hidden.height = 400; 
       var hiddenCtx = hidden.getContext('2d'); 
       hiddenCtx.strokeStyle = 'blue'; 
       hiddenCtx.fillStyle = 'yellow'; 
       hiddenCtx.lineWidth = 5; 
       //translate origin to centre of hidden canvas, and draw 3/4 of the image 
       hiddenCtx.translate(200,200); 
       for(var i=0; i<3; i++){ 
        hiddenCtx.fillRect(-170, -150, 300, 120); 
        hiddenCtx.strokeRect(-170, -150, 300, 120); 
        hiddenCtx.rotate(90*(Math.PI/180)); 
        } 
       //reset the hidden canvas to original status 
       hiddenCtx.rotate(90*(Math.PI/180)); 
       hiddenCtx.translate(-200,-200); 
       //translate to middle of visible canvas 
       ctx.translate(200, 200); 
       //repeat trick, this time copying from hidden to visible canvas 
       ctx.drawImage(hidden, 200, 0, 200, 400, 0, -200, 200, 400); 
       ctx.rotate(180*(Math.PI/180)); 
       ctx.drawImage(hidden, 200, 0, 200, 400, 0, -200, 200, 400); 
       }; 
     </script> 
    </body> 
</html> 

Demo on jsFiddle

+0

這個小提琴不起作用,你可以更新嗎? –