2014-03-06 49 views
3

我做了一些畫布,我正在繪製一個圓形和許多其他形狀。我製作了一個_rotate()函數,用於清除畫布上的內容(並刪除內容)並調用一個可以繪製正方形的函數。問題在於,點擊旋轉後,不僅畫出正方形,而且畫出圓形和矩形。我沒有任何線索可能是代碼錯誤,所以我正在採取任何建議。 的實際代碼:與html5畫布和javascript的奇怪行爲

var c = document.getElementById("canv"); 
var canvas = c.getContext("2d"); 
//ciarka 
function _rotate() { 

canvas.clearRect(0, 0, 600, 400); 
stvorec(Math.random()); 
return; 
} 


function stvorec(param) { 
canvas.rotate(param*Math.PI/180); 
canvas.fillStyle="green"; 
canvas.fillRect(350,50,50,50); 
canvas.stroke(); 
} 

function ciarka() { 
canvas.beginPath(); 
canvas.moveTo(10,10); 
canvas.lineTo(50,30); 
canvas.lineTo(100,10); 
canvas.lineTo(150,30); 
canvas.lineTo(200,10); 
canvas.lineTo(250,30); 
canvas.lineTo(300,10); 
canvas.lineTo(350,30); 
canvas.lineTo(400,10); 
canvas.lineTo(450,30); 
canvas.lineTo(500,10); 
canvas.lineTo(550,30); 
canvas.lineTo(590,10); 
canvas.stroke(); 
} 


//obdlznik 
function obdlznik() { 
canvas.rect(150,150,100,50); 
canvas.strokeStyle="black"; 
canvas.stroke(); 
} 

//kruh 
function kruh() { 
canvas.beginPath(); 
canvas.arc(200,80,50,0,2.0*Math.PI); 
canvas.stroke(); 
} 
//stvorec 

stvorec(); 
ciarka(); 
kruh(); 
obdlznik(); 

$("body").on("click", "#rot", function() { 
    _rotate(); 
}); 

的jsfiddle供參考:jsfiddle

回答

1

我看到一些小問題在你的代碼:

  • 做beginPath方法()爲每個筆劃/填充。
  • 在你的弧上做closePath()使它成爲一個圓而不是360度弧。
  • 請確保您使用.translate設置旋轉點,然後再執行.rotate
  • stvorec(Math.random())僅產生0度至1度的角度。

不是一個小故障,但只是一個命名奇怪:你稱爲你的上下文變量canvas。上下文變量通常被稱爲contextctx

我不知道你的設計要求,但這裏是一些重構工作代碼:

http://jsfiddle.net/m1erickson/5PuW9/

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 
<style> 
    body{ background-color: ivory; } 
    canvas{border:1px solid red;} 
</style> 
<script> 
$(function(){ 

    var c = document.getElementById("canv"); 
    var canvas = c.getContext("2d"); 

    //ciarka 
    function _rotate() { 
     canvas.clearRect(0, 0, 600, 400); 
     stvorec(Math.random()*360); 
    } 

    function stvorec(param) { 
     canvas.save(); 
     canvas.beginPath(); 
     canvas.translate(350,50); 
     canvas.rotate(param*Math.PI/180); 
     canvas.fillStyle="green"; 
     canvas.fillRect(-25,-25,50,50); 
     canvas.restore(); 
    } 

    function ciarka() { 
     canvas.beginPath(); 
     canvas.moveTo(10,10); 
     canvas.lineTo(50,30); 
     canvas.lineTo(100,10); 
     canvas.lineTo(150,30); 
     canvas.lineTo(200,10); 
     canvas.lineTo(250,30); 
     canvas.lineTo(300,10); 
     canvas.lineTo(350,30); 
     canvas.lineTo(400,10); 
     canvas.lineTo(450,30); 
     canvas.lineTo(500,10); 
     canvas.lineTo(550,30); 
     canvas.lineTo(590,10); 
     canvas.stroke(); 
    } 

    //obdlznik 
    function obdlznik() { 
     canvas.beginPath(); 
     canvas.rect(150,150,100,50); 
     canvas.strokeStyle="black"; 
     canvas.stroke(); 
    } 

    //kruh 
    function kruh() { 
     canvas.beginPath(); 
     canvas.arc(200,80,50,0,2.0*Math.PI); 
     canvas.closePath(); 
     canvas.stroke(); 
    } 

    //stvorec 
    stvorec(); 
    ciarka(); 
    kruh(); 
    obdlznik(); 

    $("#test").click(function() { 
     _rotate(); 
    }); 

}); // end $(function(){}); 
</script> 
</head> 
<body> 
    <button id="test">Test</button><br> 
    <canvas id="canv" width=600 height=400></canvas> 
</body> 
</html> 

[新增beginPath方法和負座標的解釋]

關於context.beginPath()

將beginPath()和fill()/ stroke()想象爲圍繞上下文路徑繪製命令所需的括號。

如果不對每個新的路徑繪製命令集執行beginPath,則在調用下一個fill()/ stroke()時將重新執行所有先前的路徑繪製命令。

例如:

// circle#1 

context.beginPath(); 
context.arc(100,100,10,0,Math.PI*2); 
context.closePath(); 
context.fillStyle=」green」; 
context.fill(); 

// circle#2 -- Note: no beginPath here 

context.arc(200,200,10,0,Math.PI*2); 
context.closePath(); 
context.fillStyle=」green」; 
context.fill(); 

在這個例子中,圓#1將被繪製。但是因爲在#2的代碼中沒有beginPath,所以#1的圓圈將會是和Circle#2一起被重畫

兩個圓都是綠色的,因爲每個beginPath只允許1個樣式(最後一個fillStyle =「綠色」將被使用,紅色樣式將不會被使用)。

關於旋轉和負座標

要旋轉,你應該告訴哪個座標要繞點的上下文。

這被稱爲設置旋轉點。默認情況下,上下文將在畫布左上角設置旋轉點,以便每個後續繪圖都將繞畫布左上角旋轉。

要設置自己的旋轉點,請執行context.translate(myCenterX,myCenterY)。

然後所有後續繪製將圍繞myCenterX,myCenterY。

認爲這是在一張紙上拿着鉛筆尖。紙張圍繞筆尖旋轉。

現在繪製矩形。

由於上下文從矩形的左上角繪製矩形,矩形將圍繞其自己的左上角旋轉。

要圍繞矩形中心旋轉,必須使用負座標將矩形向左和向上拉,直到矩形以旋轉點爲中心。

這意味着您必須fillRect(-rectWidth/2,--rectHeight/2)以使旋轉點上的矩形居中。

+0

感謝您的建議和幫助,您能否指出爲什麼每次都需要'beginPath()? 在'stvorec()'函數中,你將負值插入'fillRect()'爲什麼會這樣?在此先感謝(我只是想明白,而不僅僅是複製它) – rsz

+0

我添加了一個解釋爲什麼beginPath是每一組路徑繪圖命令需要和爲什麼需要負座標旋轉矩形圍繞其中心。乾杯! – markE

+0

感謝您的解釋,現在我明白這一點。很好的答案! – rsz

1

這裏有一個簡單的解決辦法:

//obdlznik 
function obdlznik() { 
    canvas.save(); 
    canvas.beginPath();    // add this and you're good to go! 
    canvas.rect(150, 150, 100, 50); 
    canvas.strokeStyle = "black"; 
    canvas.stroke(); 
    canvas.restore(); 
} 

Modified fiddle here

(保存/恢復是嚴格這裏沒有必要要麼)。