2011-11-06 32 views
19

Như tên tiểu bang. Điều này có thể không?Làm thế nào để vẽ phân đoạn của một chiếc bánh rán bằng canvas HTML5?

Edit: Khi tôi nói donut Ý tôi là một hàng đầu, xem 2D

là lựa chọn duy nhất để vẽ một phân đoạn của một vòng tròn, sau đó vẽ một phân đoạn của một vòng tròn nhỏ hơn với cùng một nguồn gốc và bán kính nhỏ hơn trên đầu trang, với màu nền? Điều đó sẽ là crap nếu như vậy: (

Trả lời

29

Bạn làm điều đó bằng cách làm cho một con đường duy nhất với hai vòng cung.

Bạn vẽ một vòng tròn theo chiều kim đồng hồ, sau đó vẽ vòng tròn thứ hai theo chiều ngược chiều kim đồng hồ. Tôi sẽ không đi sâu vào chi tiết của nó, nhưng cách con đường được xây dựng sẽ biết đây là một lý do để không điền vào phần đó của con đường. Để biết thêm chi tiết về những gì bạn đang làm, bạn có thể this wiki article.

Điều tương tự cũng sẽ hiệu quả nếu bạn vẽ hình chữ nhật "có khung". Bạn vẽ một ô một chiều (theo chiều kim đồng hồ), sau đó vẽ hộp bên trong theo cách khác (ngược chiều kim đồng hồ) để có hiệu ứng.

Dưới đây là mã cho một chiếc bánh rán:

var can = document.getElementById('canvas1'); 
var ctx = can.getContext('2d'); 

// Pay attention to my last argument! 
//ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); 

ctx.beginPath() 
ctx.arc(100,100,100,0,Math.PI*2, false); // outer (filled) 
ctx.arc(100,100,55,0,Math.PI*2, true); // inner (unfills it) 
ctx.fill(); 

Ví dụ:

http://jsfiddle.net/Hnw6a/

Vẽ chỉ là một "phân khúc" của nó có thể được thực hiện bằng cách làm cho con đường nhỏ (bạn có thể cần phải sử dụng beziers thay vì arc), hoặc bằng cách sử dụng một vùng cắt. Nó thực sự phụ thuộc vào chính xác như bạn muốn có một "phân khúc"

Dưới đây là một ví dụ: http://jsfiddle.net/Hnw6a/8/

// half doughnut 
ctx.beginPath() 
ctx.arc(100,100,100,0,Math.PI, false); // outer (filled) 
ctx.arc(100,100,55,Math.PI,Math.PI*2, true); // outer (unfills it) 
ctx.fill(); 
+0

aha! điều này trông giống như những gì tôi cần, cảm ơn! –

+1

Thay vì làm đầy và không làm đầy, tại sao không chỉ đột quỵ với chiều rộng chất béo? – Phrogz

+0

@Phrogz Bạn có thể muốn đường viền và tô màu là các màu khác nhau. –

1

Với WebGL (một trong những bối cảnh của canvas HTML5) có thể. Thậm chí còn có một số thư viện JS cho các trình duyệt không hỗ trợ/thực hiện nó - hãy xem các liên kết này :

+0

câu hỏi làm rõ, tôi có nghĩa là trong 2D xin lỗi. câu trả lời của bạn vẫn áp dụng? –

+0

@AndrewBullock nó áp dụng "một chút" - bạn có thể sử dụng WebGL với 2D quá nên cung cấp nhiều tùy chọn hơn cho những gì bạn muốn vẽ ... cho một ví dụ 2D đơn giản trong WebGL xem https://developer.mozilla.org/vi/WebGL/Adding_2D_content_to_a_WebGL_context – Yahia

3

Bạn có thể làm cho một 'xem donut đầu' (khoanh tròn với tâm rỗng) bằng cách vuốt ve một vòng cung. Bạn có thể xem ví dụ về điều này ở đây: http://phrogz.net/tmp/connections.html

enter image description here

Các vòng tròn (với nib) đều được vẽ bởi dòng 239-245:

ctx.lineWidth = half*0.2;   // set a nice fat line width 
var r = half*0.65;     // calculate the radius 
ctx.arc(0,0,r,0,Math.PI*2,false); // create the circle part of the path 
// ... some commands for the nib 
ctx.stroke();      // actually draw the path 
1

Với yêu cầu này, những gì @SimonSarris nói thỏa mãn các vấn đề. Nhưng hãy nói rằng bạn giống tôi và thay vào đó bạn muốn "xóa" một phần của hình dạng có thể nằm ngoài phần giới hạn của hình dạng bạn đang xóa. Nếu bạn có yêu cầu đó, giải pháp của anh ấy sẽ không khiến bạn muốn.Nó sẽ trông giống như "xor" trong hình dưới đây.

enter image description here

Các giải pháp là sử dụng context.globalCompositeOperation = 'destination-out' Các màu xanh là hình dạng đầu tiên và màu đỏ là hình dạng thứ hai. Như bạn thấy, destination-out xóa phần khỏi hình đầu tiên. Dưới đây là một số mã ví dụ:

explosionCanvasCtx.fillStyle = "red" 
    drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 

    explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html 
    drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 

Dưới đây là các vấn đề tiềm năng với điều này: Thứ hai fill() sẽ xóa tất cả mọi thứ bên dưới nó, bao gồm cả nền. Đôi khi bạn sẽ chỉ muốn xóa hình dạng đầu tiên nhưng bạn vẫn muốn xem các lớp bên dưới nó.

Giải pháp cho điều đó là vẽ hình này lên khung tạm thời và sau đó drawImage để vẽ canvas tạm thời lên khung hình chính của bạn. Mã sẽ trông như thế này:

diameter = projectile.radius * 2 
    console.log "<canvas width='" + diameter + "' height='" + diameter + "'></canvas>" 
    explosionCanvas = $("<canvas width='" + diameter + "' height='" + diameter + "'></canvas>") 
    explosionCanvasCtx = explosionCanvas[0].getContext("2d") 

    explosionCanvasCtx.fillStyle = "red" 
    drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 

    explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html 
    durationPercent = (projectile.startDuration - projectile.duration)/projectile.startDuration 
    drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius) 
    explosionCanvasCtx.fill() 
    explosionCanvasCtx.globalCompositeOperation = 'source-over' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html 

    ctx.drawImage(explosionCanvas[0], projectile.pos.x - projectile.radius, projectile.pos.y - projectile.radius) #center 
2

Vâng, tôi hiểu bao nhiêu tuổi câu hỏi này là :)

Dưới đây là hai của tôi cent:

(function(){ 
var annulus = function(centerX, centerY, 
         innerRadius, outerRadius, 
         startAngle, endAngle, 
         anticlockwise) { 
    var th1 = startAngle*Math.PI/180; 
    var th2 = endAngle*Math.PI/180; 
    var startOfOuterArcX = outerRadius*Math.cos(th2) + centerX; 
    var startOfOuterArcY = outerRadius*Math.sin(th2) + centerY; 

    this.beginPath(); 
    this.arc(centerX, centerY, innerRadius, th1, th2, anticlockwise); 
    this.lineTo(startOfOuterArcX, startOfOuterArcY); 
    this.arc(centerX, centerY, outerRadius, th2, th1, !anticlockwise); 
    this.closePath(); 
} 
CanvasRenderingContext2D.prototype.annulus = annulus; 
})(); 

nào sẽ bổ sung thêm một chức năng "annulus () "tương tự như" arc() "trong nguyên mẫu CanvasRenderingContext2D. Làm cho đường dẫn khép kín trở nên hữu ích nếu bạn muốn kiểm tra sự bao gồm điểm.

Với chức năng này, bạn có thể làm một cái gì đó như:

var canvas = document.getElementById("canvas1"); 
var ctx = canvas.getContext("2d"); 
ctx.annulus(0, 0, 100, 200, 15, 45); 
ctx.fill(); 

Hoặc kiểm tra này: https://jsfiddle.net/rj2r0k1z/10/

Cảm ơn!

+0

Cảm ơn bạn. Hôm nay tôi sẽ sử dụng rất nhiều điều này:) – T4NK3R

0

Thích ứng/đơn giản hóa câu trả lời @Simon Sarris để dễ dàng làm việc với bất kỳ góc đưa ra dưới đây:

Để tạo phân đoạn arc bạn vẽ một vòng cung bên ngoài (n radian) theo một hướng và sau đó một vòng cung ngược (của cùng số radian) tại bán kính nhỏ hơn và điền vào vùng kết quả.

var can = document.getElementById('canvas1'); 
 
var ctx = can.getContext('2d'); 
 
    
 
var angle = (Math.PI*2)/8; 
 

 
var outer_arc_radius = 100; 
 
var inner_arc_radius = 50.; 
 

 
ctx.beginPath() 
 

 
//ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); 
 
ctx.arc(100,100,outer_arc_radius,0,angle, false); // outer (filled) 
 
// the tip of the "pen is now at 0,100 
 
ctx.arc(100,100,inner_arc_radius,angle,0, true); // outer (unfills it) 
 
ctx.fill();
<canvas id="canvas1" width="200" height="200"></canvas>

Các vấn đề liên quan