In Javascript canvas drawing, how do you eliminate the line in arc()?
I'm trying to draw an arc on a canvas in Javascript, but I want to get rid of the line that Javascript automatically draws. With the line being drawn, there are two problems: a) fill() malfunctions b) It looks like a bow
Here's an image of what I have and what I want:
The left is what I have in JS, the right is what I have in Java. The Java implementation is fairly inefficient and I would like to use the functions already available.Here are the relevant JS functions:
function pointAt(center, l, theta){
return {
x : Math.sin(theta) * l + center.x,
y : Math.cos(theta) * l + center.y
};
}
function drawArc(ctx, center, l, theta, sweep, label, thickness){
var p0 = pointAt(center, l, theta);
var p1 = pointAt(center, l + thickness, theta);
var p2 = pointAt(center, l + thickness, theta + sweep);
var p3 = pointAt(center, l, theta + sweep);
ctx.fillStyle = "red";
drawPoint(ctx, p0);
ctx.fillStyle = "blue";
drawPoint(ctx, p1);
ctx.fillStyle = "green";
drawPoint(ctx, p2);
ctx.fillStyle = "yellow";
drawPoint(ctx, p3);
ctx.beginPath();
ctx.moveTo(p0.x, p0.y);
ctx.lineTo(p1.x, p1.y);
ctx.arc(center.x, center.y, l + thickness, theta, theta + sweep, false);
ctx.moveTo(p2.x, p2.y);
ctx.lineTo(p3.x, p3.y);
ctx.arc(center.x, center.y, l, theta + sweep, theta, true)
ctx.closePath();
ctx.fill();
ctx.stroke();
//TODO: draw label!!!
}
function drawPoint(ctx, p){
ctx.fillRect(p.x - 4, p.y - 4, 8, 8);开发者_如何学Go
}
Here's a working implementation in Java:
private static void drawArc(Graphics g, Point center, int l, double theta, double sweep, String label, int thickness){
for (double i = 0; i < thickness; i+=.5) { //hardcoded
Point last = pointAt(center, l + i, theta);
for(double t = theta; t < theta + sweep; t+=.01){
Point cur = pointAt(center, l + i, t);
g.drawLine(last.x, last.y, cur.x, cur.y);
last = cur;
}
}
double t = theta + sweep / 2;
Point p = pointAt(center, l + 15, t);
int size = g.getFontMetrics().stringWidth(label);
BufferedImage img = new BufferedImage(size * 2, size * 2, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setColor(Color.RED);
double rot = (Math.PI / 2 - t);
// System.out.println(rot / Math.PI + "PI");
boolean b = true;
if(rot < -Math.PI / 2){
rot += Math.PI;
b = false;
}
g2.setTransform(AffineTransform.getRotateInstance(rot, size, size));
g2.drawString(label, size, size);
g2.dispose();
if(!b)
size *= 1.75; //magic value or hardcoded???
g.drawImage(img, p.x - size, p.y - size, null);
}
So my question: How do I turn the banana into a thick arc?
Just draw the outer arc clockwise, then the inner arc counter-clockwise. The canvas will automatically close off the ends with straight lines for you.
var c = document.getElementById('c');
var ctx = c.getContext('2d');
ctx.beginPath();
ctx.arc(0,0,50,0,-Math.PI * 0.5, false);
ctx.arc(0,0,25,-Math.PI * 0.5,0, true);
ctx.fillStyle = '#0f0';
ctx.fill();
ctx.strokeStyle = '#0f0';
ctx.stroke();
ctx.closePath();
http://jsfiddle.net/tMEdq/
Also, here are good references: http://diveintohtml5.ep.io/canvas.html#divingin http://www.nihilogic.dk/labs/canvas_sheet/HTML5_Canvas_Cheat_Sheet.png
You have way too many drawing calls too - this is all you need:
ctx.beginPath();
ctx.arc(center.x, center.y, l + thickness, theta, theta + sweep, false);
ctx.arc(center.x, center.y, l, theta + sweep, theta, true);
ctx.closePath();
ctx.fill();
ctx.stroke();
Just draw the first arc, which will automatically get joined to the next, and then close the path to complete the loop.
You also have your sin
and cos
calls the wrong way around in pointAt()
- sin()
should alter the Y axis coordinate, not the X axis!
Working demo at http://jsfiddle.net/alnitak/zChSe/
Just do:
function drawArc(ctx, center, l, theta, sweep, label, thickness){
var p0 = pointAt(center, l, theta);
var p1 = pointAt(center, l + thickness, theta);
var p2 = pointAt(center, l + thickness, theta + sweep);
var p3 = pointAt(center, l, theta + sweep);
ctx.fillStyle = "red";
drawPoint(ctx, p0);
ctx.fillStyle = "blue";
drawPoint(ctx, p1);
ctx.fillStyle = "green";
drawPoint(ctx, p2);
ctx.fillStyle = "yellow";
drawPoint(ctx, p3);
ctx.beginPath();
//ctx.moveTo(p0.x, p0.y);
//ctx.lineTo(p1.x, p1.y);
ctx.arc(center.x, center.y, l + thickness, theta, theta + sweep, false);
//ctx.moveTo(p2.x, p2.y);
//ctx.lineTo(p3.x, p3.y);
ctx.arc(center.x, center.y, l, theta + sweep, theta, true);
ctx.closePath();
ctx.fill();
ctx.stroke();
//TODO: draw label!!!
}
The "lateral" lines are implict placed, see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc.
精彩评论