復制代碼代碼如下: //-----------用參數方程繪制橢圓--------------------- //函數的參數x,y為橢圓中心;a,b分別為橢圓橫半軸、 //縱半軸長度,不可同時為0 //該方法的缺點是,當linWidth較寬,橢圓較扁時 //橢圓內部長軸端較為尖銳,不平滑,效率較低 function ParamEllipse(context, x, y, a, b) { //max是等于1除以長軸值a和b中的較大者 //i每次循環增加1/max,表示度數的增加 //這樣可以使得每次循環所繪制的路徑(弧線)接近1像素 var step = (a b) ? 1 / a : 1 / b; context.beginPath(); context.moveTo(x + a, y); //從橢圓的左端點開始繪制 for (var i = 0; i 2 * Math.PI; i += step) { //參數方程為x = a * cos(i), y = b * sin(i), //參數為i,表示度數(弧度) context.lineTo(x + a * Math.cos(i), y + b * Math.sin(i)); } context.closePath(); context.stroke(); };
復制代碼代碼如下: //------------均勻壓縮法繪制橢圓-------------------- //其方法是用arc方法繪制圓,結合scale進行 //橫軸或縱軸方向縮放(均勻壓縮) //這種方法繪制的橢圓的邊離長軸端越近越粗,長軸端點的線寬是正常值 //邊離短軸越近、橢圓越扁越細,甚至產生間斷,這是scale導致的結果 //這種缺點某些時候是優點,比如在表現環的立體效果(行星光環)時 //對于參數a或b為0的情況,這種方法不適用 function EvenCompEllipse(context, x, y, a, b) { context.save(); //選擇a、b中的較大者作為arc方法的半徑參數 var r = (a b) ? a : b; var ratioX = a / r; //橫軸縮放比率 var ratioY = b / r; //縱軸縮放比率 context.scale(ratioX, ratioY); //進行縮放(均勻壓縮) context.beginPath(); //從橢圓的左端點開始逆時針繪制 context.moveTo((x + a) / ratioX, y / ratioY); context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI); context.closePath(); context.stroke(); context.restore(); };
復制代碼代碼如下: //---------使用三次貝塞爾曲線模擬橢圓2--------------------- //此方法也會產生當lineWidth較寬,橢圓較扁時 //,長軸端較尖銳,不平滑的現象 //這種方法比前一個貝塞爾方法精確度高,但效率稍差 function BezierEllipse2(ctx, x, y, a, b) { var k = .5522848, ox = a * k, // 水平控制點偏移量 oy = b * k; // 垂直控制點偏移量 ctx.beginPath(); //從橢圓的左端點開始順時針繪制四條三次貝塞爾曲線 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(); };