How to draw an ellipse on canvas

Source: Internet
Author: User

This article belongs to the HTML5 canvas painting series tutorial

In the canvas, you can easily draw a circle using the arc method. Originally, the circle can be regarded as an elliptic with equal width and height, but there is no elliptical method in the canvas, we need to simulate it using other methods.

First, we need to specify the parameters required to draw an elliptic. The basic geometric knowledge tells us that the elliptic requires the coordinates of the center, width, height, or rotation angle. However, this can be avoided for the time being, it is easier to rotate.

1. Use lineto to draw an ellipse

You are not mistaken. A method like lineto that is purely used to draw a straight line can actually be used to draw an elliptic !? But he does exist, but the writing method is incredible:

 Function  Drawellipse (canvas, O, OA, ob ){  //  Draw an ellipse, for example: var B = new array (150,150); drawellipse (Hb, B, 50, 30 );      With  (Canvas ){  VaR X = O [0] + OA;  VaR Y = O [1 ]; MoveTo (x, y );  For ( VaR I = 0; I <= 360; I ++ ){  VaR II = I * Math. PI/180; VaR X = O [0] + oa * Math. Cos (II );  VaR Y = O [1]-OB * Math. Sin (II); lineto (x, y );}}} 

The principle of this method is that a circle has 360 degrees, so we use lineto to cycle 360 times, draw a line segment of each degree, and finally form an elliptic. The sine cosine of the trigonometric function is used for calculation.

Note that the first parameter of this method is an array, that is, the coordinates of the center of the elliptical circle.

The idea is amazing, and the elliptic plot is also smooth. But it is not worth using-every time you draw an elliptical image in this method, it will take 360 cycles. As long as there are more than one elliptical image, it will be a test of the browser's performance.

We just need to understand his ideas.

2. Use arc to draw a circle and then scale it into an elliptic

The original method is as follows:

 VaR Canvas = Document. getelementbyid ('mycanvas' );  VaR Context = canvas. getcontext ('2d' );  VaR Centerx = 0 ;  VaR Centery = 0 ;  VaR Radius = 50 ;  //  Save state Context. Save ();  //  Translate Context Context. Translate (canvas. width/2, canvas. Height/2 );  //  Scale context horizontally Context. Scale (2, 1 );  //  Draw circle which will be stretched into an oval  Context. beginpath (); context. ARC (centerx, centery, radius, 0, 2 * Math. Pi, False  ); //  Restore to original state Context. Restore ()

This method uses a canvas function that I have not mentioned before, that is, scale, which can scale the canvas. Zooming has two directions: horizontal and vertical,CodeThe horizontal direction of the canvas is enlarged, while the vertical direction remains unchanged. So, the original circle drawn by the arc turns into an elliptical.

This method is very good at the beginning, with few codes and easy-to-understand principles. But after analysis, we can find out his obvious weakness, that is, the inaccuracy! For example, if I need an elliptic with a width of 171 and a height of 56, if we set the Arc Radius to 28, then we will be depressed by the yundun Number of 171/28/2.

However, there is a way to always set the Arc Radius to 100, and then zoom in if it is not enough. However, it is still inaccurate.

3. Use the beziercurveto Curve

Since I think the scaling method above is not accurate, I really want to find a precise method for drawing an ellipse. Finally, I found it on stackoverflow:

 Function  Drawellipse (CTX, X, Y, W, h ){  VaR Kappa = 0.5522848 ; Ox = (W/2) * kappa,//  Control Point offset horizontal Oy = (H/2) * kappa, //  Control Point offset vertical Xe = x + W, //  X-end Ye = Y + H, //  Y-end XM = x + W/2, //  X-middle Ym = Y + H/2; //  Y-middle CTX. beginpath (); CTX. moveTo (x, ym); CTX. beziercurveto (x, ym -Oy, XM- Ox, Y, XM, Y); CTX. beziercurveto (XM + Ox, Y, XE, ym- Oy, XE, ym); CTX. beziercurveto (xe, ym + Oy, XM + Ox, ye, XM, ye); CTX. beziercurveto (XM -Ox, ye, X, ym + Oy, X, ym); CTX. closepath (); CTX. Stroke ();} 

This method is perfect. He divided an elliptic into four besell curves and connected them into an elliptic. In the end, the width and height are also relatively accurate, and the overhead is also small.

However, this method still has shortcomings. Looking at the variable Kappa, there is a very strange value. I believe many people have asked you why he wants to take this value before the geometric experts tell you, I still don't know why I have to take this value. And I have a strong urge to change him to see what the consequences are.

Of course, the impulse of a patient similar to obsessive-compulsive disorder cannot be said to be a weakness of this method. His real weakness is: why should we use four besels? In my opinion, an elliptic is obviously composed of two besell curves rather than four. This idea eventually gave me the perfect way to draw an elliptical image.

4. Draw an ellipse using two besell Curves

To learn whether the previous method can be simplified, I registered a stackoverflow account to ask questions. Because there are images in the problem, the points cannot be transferred due to insufficient points, I have no choice but to use strong English skills to answer questions from foreigners and earn points. However, when I finally got lucky, I answered a question and solved my points.

I raised the original question here.

To be honest, I did not understand most of the answers below, but fortunately he provided a sample code page to help me understand the principles. I would like to express my gratitude to him again. According to his answers, the following method is used to draw an elliptical image:

 //  Elliptic Canvasrenderingcontext2d. Prototype. oval = Function  (X, y, width, height ){  VaR K = (width/0.75)/2 , W = Width/2, H = height/2; This  . Beginpath ();  This . MoveTo (X, Y-H );  This . Beziercurveto (x + k, Y-h, x + k, Y + H, X, Y + H );  This . Beziercurveto (X-K, Y + H, X-K, Y-h, X, Y- H );  This  . Closepath ();  Return   This  ;} 

This method is both accurate and less code, and there is no strange and difficult to understand. You only need to remember this. The ratio of the width of the elliptic to the coordinates of the control points of the elliptic besell curve is as follows:

 
Besell control point X = (elliptical width/0.75)/2

This is already reflected in the Code.

You can test the above four methods to draw an ellipse.

If you find a simpler method, share it with you. Or, click "recommendation" for me.

Original. Reprinted, Please retain.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.