Four Methods for drawing an ellipse in HTML5 Canvas: html5canvas

Source: Internet
Author: User

Four Methods for drawing an ellipse in HTML5 Canvas: html5canvas
This article mainly introduces four methods for drawing an ellipse in HTML5 Canvas. 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: </p> <p> // ------------ draw an elliptic ------------------ by means of uniform compression --------------------
// 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; </p> <p> 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 (); </p> <p> };

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 </p> <p> 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:
<Div id = "CanvasWrap" style = "background: # fff; width: 600px; height: 600px; border: 1px solid black; "> </div> </p> <script type =" text/javascript "> // <! [CDATA [
Var canvas,
Context;
Var div = document. getElementById ("CanvasWrap ");
Div. innerHTML = "";
Canvas = document. createElement ("canvas ");
Canvas. style. width = "600px"
Canvas. style. height = "600px"
Canvas. width = 600;
Canvas. height = 600;
Context = canvas. getContext ("2d ");
Div. appendChild (canvas); </p> <p> function execDraw ()
{
// Solve the problem that the width of Chrome is less than or equal to 1
Context. lineWidth = 1.1;
Context. strokeStyle = "black"
ParamEllipse (context, 130, 80, 50, 50); // circle
ParamEllipse (context, 130, 80,100, 20); // elliptic
EvenCompEllipse (context, 130,200, 50, 50); // circle
EvenCompEllipse (context, 130,200,100, 20); // elliptic
BezierEllipse1 (context, 470, 80, 50, 50); // circle
BezierEllipse1 (context, 470, 80,100, 20); // elliptic
BezierEllipse2 (context, 470,200, 50, 50); // circle
BezierEllipse2 (context, 470,200,100, 20); // elliptic
// Detect similarity (degree of coincidence)
ParamEllipse (context, 300,450,250, 50 );
Context. strokeStyle = "yellow ";
BezierEllipse1 (context, 300,450,250, 50 );
Context. strokeStyle = "blue ";
BezierEllipse2 (context, 300,450,250, 50 );
}; </P> <p> function compute avnas ()
{
Context. clearRect (0, 0,600,600 );
};
//]> </Script> </p> <p>

<Button onclick = "execDraw ();" type = "button"> RUN </button>
<Button onclick = "clearCanvas ();" type = "button"> clear </button>
</P>

Note: To successfully run the code, you must support the HTML5 Canvas browser.

Related Article

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.