Recently, I was asked how to draw an ellipse in canvas. As a front-end engineer, I have little contact with graphics and WebGL, and my knowledge of Canvas is limited to the API corresponding to canvas drawing. When I encountered this problem, I was completely confused. I vaguely remember that canvas has a circle drawing API, and I took it for granted that there should also be a corresponding API for ellipse drawing. Pass in the coordinate point/long axis/short axis parameters. After the special try and research, share.

How does canvas draw circles

Native API: Arc Receive 😡 /y/start Angle/end Angle/draw direction False for clockwise (default) several parameters

 const ctx = canvas.getContext('2d');
 ctx.arc(x,y,radius,startAngle,endAngle,anticlockwise)
Copy the code

Understand, in fact, the internal call of the computer is grating, the parameter equation of the circle x= Rcos θ y=rsinθ, so you can write a method to draw a circle

function circle(context, x, y, r) {
    const step = 1/r; 
    context.beginPath();
    context.moveTo(x + r, y);
    for(let i = 0; i < 2 * Math.PI; i += step) {
        context.lineTo(x + r * Math.cos(i), y + r * Math.sin(i));
    }
    context.closePath();
    context.fill();
}
Copy the code
X and y are coordinates, r is radius, and 1/r is the Angle value corresponding to the line segment 1px, which is also the degree of fineness. When r is large, a fixed value can be written, such as 1/10, otherwise performance will be affectedCopy the code

Start drawing an ellipse

In fact, the latest version of Chrome has a native ellipse drawing API, but compatibility is not very good, x /y/horizontal axis length/vertical axis length/rotation Angle/actual Angle/end Angle/direction

  ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
Copy the code

Similarly to circles, you can implement a method of drawing an ellipse by using the parametric equation of the ellipse: x= ACos θ | y=bsinθ

function ellipse(context, x, y, a, b) { const step = (a > b) ? 1 / a : 1 / b; context.beginPath(); context.moveTo(x + a, y); for (let i = 0; i < 2 * Math.PI; i += step) { context.lineTo(x + a * Math.cos(i), y + b * Math.sin(i)); } context.closePath(); CTX. FillStyle = "rgba (0, 0,. 2)"; context.fill(); }Copy the code
Parameters and the original and draw the circle similar, step can be adjusted according to the actual situationCopy the code

There is a simpler and more efficient way to compress the standard circle into an ellipse, as you can see from the code, but with this method the width is also compressed when the border width is larger

function ellipse(context, x, y, a, b) { context.save(); const r = (a > b) ? a : b; const ratioX = a / r; const ratioY = b / r; context.scale(ratioX, ratioY); context.beginPath(); context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI, false); context.closePath(); context.restore(); CTX. FillStyle = "rgba (255, 0, 2)"; context.fill(); }Copy the code
With your mutual encouragement, need to learn a lot.Copy the code

Finally, I recommend a canvas related address: address