html 5 Canvasプロット11:楕円形

4098 ワード

本文は『html 5 Canvas画図シリーズチュートリアル』に属する
canvasではarc法で円形を描くのが便利で、もともと円形も幅が同じ楕円と見なすことができますが、canvasでは楕円を描く方法はまったくありません.他の方法でシミュレーションします.まず、楕円を描くにはパラメータが必要であることを明確にしなければなりません.基本的な幾何学的知識は、楕円には円心座標、幅、高さ--あるいは回転角度が必要ですが、これは一時的にやめてもいいです.回転は簡単です.
1、lineToで楕円を描く
あなたは間違っていません.lineToのような純粋に直線を描く方法が楕円を描くことができます!?しかし、彼は確かに存在していますが、書き方は不思議です.
function DrawEllipse(Canvas,O,OA,OB){
    //   ,  :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);
        }
    }
}

この方法の原理は、1つの円が360度あるので、lineToで360回循環して、1回の線分を描いて、最終的に楕円につながっています.ここでは、三角関数の正弦余弦を使用して計算する必要があります.なお、この方法の2番目のパラメータは、楕円の円心座標である配列である.奇抜な発想で、楕円も滑らかに描かれています.しかし、みんなが使う価値はありません.この方法は楕円を描くたびに360回循環し、絵の楕円だけが少し多く、ブラウザの性能に試練があります.私たちは彼の考えを理解するだけでいい.
2、arcを使って円を描き、楕円に拡大縮小する
この方法の原文はここで、コア関数は以下の通りです.
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()
}

この方法は私が前に話したことのないcanvas関数、すなわちscaleを使って、彼はcanvasのスケールを実現することができます.スケールは水平と垂直の2つの方向があり、コードの中でcanvasの水平方向を拡大したが、垂直方向は変わらず、so、arcが描いた円形は楕円になった.この方法は初めはすばらしく,コードが少なく,原理が分かりやすい.しかし、分析すると彼の明らかな欠点が発見されます.--正確ではありません.例えば私は幅171の高さ56の楕円が必要で、この時私たちはarcの半径を28にすれば、後ろは171/28/2という卵の痛みの何が起こっているのか分からない数字に憂鬱になります.しかし、arcの半径を常に100に設定し、足りないと拡大し、超えたら縮小する方法があります.しかし、まだ正確ではない.
3、ベゼル曲線bezierCurveToを使う
上のスケーリングが不正確だと思ってから、正確な楕円を描く方法を見つけたいと思っていましたが、最後に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();
}

この方法は比較的完璧だと言える.彼は1つの楕円を4つのベッセル曲線に分けて、彼らで1つの楕円につながった.最後に幅の高さも正確で、オーバーヘッドも少ない.しかし、この方法には依然として欠点がある.みんなはそのkappaパラメータを見て、とても奇抜な値があって、多くの人が幾何学の専門家があなたになぜ彼がこの値を取るのかを教える前に、どうしてこの値を取らなければならないのか分からないと信じています--私は今でも知りません.そして私は彼を変えて何か結果があるかを見たいという衝動が強い.もちろん私のような強迫症患者の衝動はこの方法の欠点とは言えないが、彼の本当の欠点は--なぜ4本のベッセル曲線を使うのか.個人的には、1つの楕円は明らかに4本ではなく2本のベッセル曲線から構成されていると思います.この考えは最終的に私に最も完璧な楕円を描く方法を見つけた.
4、2本のベゼル曲線で楕円を描く
前の方法が簡略化できるかどうかを知るために、私はstackoverflowのアカウントを登録して質問しました.質問には画像があるので、ポイントが足りなくて伝わらないので、私はやむを得ず無理な英語のレベルで外国人の質問に答えてポイントを稼ぎました.しかし、最終的に幸運に恵まれ、一つの質問に答えて私のポイントの問題を解決しました.私が提案したベゼル曲線と楕円の関係の問題はここにある.正直に言うと、次の外国人の答えはほとんど読めませんでしたが、コードのサンプルページを提供してくれて、原理を理解させてくれて、ここで彼に再び感謝します.彼の答えによると、私が見つけた楕円を描く方法は以下の通りです.
//  
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;
}

この方法は正確で、コードも少ないし、変な難解なところもありません.この点を覚えておくだけで、楕円の幅と楕円を描いたベゼル曲線の制御点の座標の割合は以下の通りです.
      x=(    /0.75)/2

この点はすでにコードに現れている.上の4つの方法で楕円を描くことができます.
もっと簡単な方法を見つけたら、みんなで検討してください.
閲覧ありがとうございます!あなたに役に立つことを望みます!あなたの支持は私の原動力です!質問があればQQ:56084073に連絡してください.