This article mainly introduces four methods for drawing an ellipse in HTML5Canvas. This article describes four methods, including parameter equation method, uniform compression method, cubic besell curve method, and grating method, for more information, see
Overview
Canvas in HTML5 does not directly provide the method for drawing an ellipse. The following is a summary of several painting methods. Various methods have advantages and disadvantages, which are selected as needed. The parameters of each method are the same:
1. context is the 2D drawing environment object of Canvas,
2. x is the abscissa of the center of the ellipse,
3. y is the vertical coordinate of the elliptical center,
4. a is the length of the horizontal and semi-axes of the elliptic,
5. B is the length of the oval longitudinal Half Axis.
Parameter Equation Method
This method uses the parameter equation of the elliptic to plot the elliptic
The Code is as follows:
// ----------- Use the parameter equation to draw an elliptic ---------------------
// The x and y parameters of the function are the center of the elliptic; the and B parameters are the cross and semi axes of the elliptic,
// The length of the vertical and semi-axis, which cannot be 0 at the same time
// The disadvantage of this method is that when the lineWidth is wide and the ellipse is relatively flat
// The end of the long axis inside the elliptical is sharp, insmooth, and inefficient.
Function ParamEllipse (context, x, y, a, B)
{
// Max is equal to 1 divided by the greater of the long axis values a and B
// I increases by 1/max each cycle, indicating an increase in the degree
// This will make the path (ARC) drawn by each loop close to 1 pixel
Var step = (a> B )? 1/a: 1/B;
Context. beginPath ();
Context. moveTo (x + a, y); // draw from the left endpoint of the ellipse
For (var I = 0; I <2 * Math. PI; I ++ = step)
{
// The parameter equation is x = a * cos (I), y = B * sin (I ),
// The parameter is I, indicating the degree (radian)
Context. lineTo (x + a * Math. cos (I), y + B * Math. sin (I ));
}
Context. closePath ();
Context. stroke ();
};
Uniform Compression Method
This method uses the principle of uniform compress in mathematics to compress the circle evenly into an elliptic. Theoretically, a standard elliptic can be obtained. the following code shows the line width inconsistency. For the solution, see simonleung's comment on the fifth floor.
The Code is as follows:
// ------------ Draw an elliptic using the uniform compression method --------------------
// The method is to use the arc method to draw a circle and scale the circle.
// Horizontal or vertical scaling (even compression)
// The longer the side of the ellipse drawn by this method, the closer it is to the end of the long axis, and the longer the width of the end of the long axis is normal.
// The closer the edges are from the short axis, the thinner the oval is, and even interrupted. This is the result of scale.
// This disadvantage is sometimes an advantage, for example, when it represents the three-dimensional effect of the ring (planetary halo)
// This method is not applicable when the value of a or B is 0.
Function EvenCompEllipse (context, x, y, a, B)
{
Context. save ();
// Select the greater one in a and B as the radius parameter of the arc method.
Var r = (a> B )? A: B;
Var ratioX = a/r; // horizontal scaling ratio
Var ratioY = B/r; // zooming ratio of the vertical axis
Context. scale (ratioX, ratioY); // scale (even compression)
Context. beginPath ();
// Draw counter-clockwise from the left endpoint of the ellipse
Context. moveTo (x + a)/ratioX, y/ratioY );
Context. arc (x/ratioX, y/ratioY, r, 0, 2 * Math. PI );
Context. closePath ();
Context. stroke ();
Context. restore ();
};
Cubic besell curve method 1
The elliptic plot of cubic besell curves is an approximation in actual drawing and theoretically an approximation. However, because of its high efficiency, it is often used in computer vector graphics to draw an ellipse, but I am not very clear about the specific theory. The approximation lies in the selection of two control points. The position of the control point of this method is obtained by myself, and the accuracy is also acceptable.
The Code is as follows:
// --------- Use cubic besell curves to simulate an elliptic 1 ---------------------
// This method also produces when the lineWidth is wider and the ellipse is relatively flat,
// Sharp and non-smooth long axis
Function BezierEllipse1 (context, x, y, a, B)
{
// The key is the setting of two control points in bezierCurveTo.
// 0.5 and 0.6 are two key coefficients (obtained for experiment in this function)
Var ox = 0.5 *,
Oy = 0.6 * B;
Context. save ();
Context. translate (x, y );
Context. beginPath ();
// Draw in the clockwise direction from the lower end of the elliptical vertical axis
Context. moveTo (0, B );
Context. bezierCurveTo (ox, B, a, oy, a, 0 );
Context. bezierCurveTo (a,-oy, ox,-B, 0,-B );
Context. bezierCurveTo (-ox,-B,-a,-oy,-a, 0 );
Context. bezierCurveTo (-a, oy,-ox, B, 0, B );
Context. closePath ();
Context. stroke ();
Context. restore ();
};
Cubic besell curve method 2
This method is changed from the reply of a post in StackOverFlow, with a high accuracy and is usually used to draw an elliptic.
The Code is as follows:
// --------- Use cubic besell curves to simulate an elliptic 2 ---------------------
// This method also produces when the lineWidth is wider and the ellipse is relatively flat.
// The long axis is sharp and insmooth.
// This method is more accurate than the previous besell method, but less efficient
Function BezierEllipse2 (ctx, x, y, a, B)
{
Var k =. 5522848,
Ox = a * k, // horizontal control point offset
Oy = B * k; // Vertical Control Point offset
Ctx. beginPath ();
// Draw four cubic besell curves clockwise from the left endpoint of the ellipse
Ctx. moveTo (x-a, y );
Ctx. bezierCurveTo (x-a, y-oy, x-ox, y-B, x, y-B );
Ctx. bezierCurveTo (x + ox, y-B, x + a, y-oy, x + a, y );
Ctx. bezierCurveTo (x + a, y + oy, x + ox, y + B, x, y + B );
Ctx. bezierCurveTo (x-ox, y + B, x-a, y + oy, x-a, y );
Ctx. closePath ();
Ctx. stroke ();
};
Grating Method
This method can be used to draw an ellipse based on the Basic Algorithms in graphics based on the features of Canvas's ability to operate pixels. For example, the midpoint painting elliptic algorithm.
One example is a blog post "HTML5 Canvas improvement class (1)-grating graphics (1) MidPoint Circle Algorithm" by yuanyou "Doudou dog ". This method is relatively "primitive", with great flexibility, high efficiency, and high accuracy. However, it is complicated to implement a useful Elliptical Function. For example, when the line width changes, the algorithm is more complex. Although it is an algorithm for circle painting, the algorithm for elliptical painting is similar. For details, refer.
Summary
Basically, none of the methods can achieve 100% accuracy, because of the limitation of the display resolution.
In fact, the best method should be arc () + scale (). This method is used in the canvas plotting library KineticJS.
In other plotting software, unlike the HTML5 canvas, the inherent arc () + scale () method is provided. Generally, the besell curve is used to simulate an approximate elliptic, no matter how many besell curves are, they are all similar. For details about how to use the besell curve to simulate an ellipse, refer to this document: Drawing an elliptical arc using polylines, quadratic or cubic bezr curves.
Since arc () + scale () is a method that has been implemented by the browser and has the highest accuracy in theory, it is the best in terms of efficiency, accuracy, and ease of use.
After the elliptic is drawn using arc () + scale (), context. stroke () and context. the Calling sequence of the restore () method is different, and the results are very interesting. Generally, you should first restore () and then stroke ().
Demo
The following is a demo of drawing an Elliptical Function in addition to the grating method. The Demo code is as follows:
The Code is as follows: