I decided to do a page just on this since arcTo() is so confusing to everyone. In fact, it's so confusing that several of the browsers got their implementation wrong. As of this writing some implementations are still buggy, but most of them will draw arcTo() correctly now. I was just looking at this in the SeaMonkey browser and it has some bugs that are already fixed in the Mozilla trunk that make the arcs go crazy. I run Ubuntu, and their package for SeaMonkey is way behind Mozilla. The Firefox browser, on the other hand, works just fine. Opera, as of this writing, also has problems with arcTo. So, if this doesn't work right on your browser, I apologize, but you'll just have to upgrade to a newer version, switch browsers, or wait until they fix your browser.
Although you pass two points to arcTo(), there're actually three points involved in the whole thing. There's (x0,y0), which is whatever the current point in the path is before you call arcTo. Additionally, there are (x1,y1) and (x2,y2) the two control points you pass to arcTo(). Finally, there is a radius that you pass in that will be the radius of an imaginary circle we'll talk about in just a second.
It works like this. Draw an imaginary line through (x0,y0) and (x1,y1). Draw another imaginary line through (x1,y1) and (x2,y2).
Take an imaginary circle of radius r, and slide it up between the two lines until it just touches both lines. The two points at which the circle touches the lines are called the tangent points.
It's really quite easy to make a rounded rectangle.
At this point this should be pretty self evident. We define a function to do the rounded rectangles for us. It has to know where rectangle starts, what size it is, how rounded we want the corners, and whether we want it filled or stroked or both. Then it does it for us using the currently set strokeStyle and fillStyle.
Once we've defined it, it's an easy matter to call it twice to draw two rectangles with rounded corners.
The first one is both filled and stroked. Its corners have a radius of 20, it's filled in green, and it's stroked in red.
The second rectangle is only filled. Its corners have a radius of 40, and it's filled in blue. For fun, I made the blue transparent by using rgba(0,0,150,0.6) for the fillStyle. The last argument, 0.6 , can range in value from 0.0, completely transparent, to 1.0, completely opaque. When we use rgb() with only 3 arguments, the colors are always opaque.
I'd like to thank Eric Fredricksen who pointed out that I didn't need any lineTo calls in the roundedRect() routine when using arcTo() and made my tutorial and my code more elegant.
First we draw the line of the shaft, then a line back to the top back corner of the arrow head. That will be the first control point. Then we pass the tip of the arrow head and the bottom back corner of the arrow head as the other two control points and ask for a radius of eight. As soon as we stroke and fill it, we get a beautiful arrow head. If you want to know more about drawing arrows and arcs, I have a whole tutorial on it, Drawing lines and arcs with arrow heads on HTML5 Canvas.
I hope this helped to clear up any confusion, and I hope you keep learning. It's my favorite thing to do.