1つのアプリケーションを開発する過程で、JavaScriptのキャンバスに任意の角度で楕円を描画する必要に直面しました。 このような単純なプロジェクトではフレームワークを使いたくなかったので、このトピックに関するマニュアル記事を探しました。 検索が失敗したため、私は自分でタスクを処理する必要があり、私はあなたと得た経験を共有することにしました。
問題を形式化します。
drawEllipse関数
(coords、sizes、vector)が必要です。ここで:
- coords-楕円の中心の座標-配列[x、y]
- サイズ-楕円の長軸と短軸の長さ-配列[a、b]
- vector-楕円の勾配のベクトル[x、y]
この記事では、この問題を解決する3つの方法を提供します。
最初の方法としてベジェ曲線が選択されました。 このような曲線を作成するには、開始点、終了点、2つの制御点の4つの点が必要です。

目的の楕円は、このような2つの曲線で構成され、それぞれの上記の点が長方形の頂点になると推測するのは簡単です。 楕円を見てみましょう。

- ベクトルがあります

単位ベクトルを見つける 


単位ベクトルを見つける 
これを行うには、ベクトルのスカラー積のプロパティを思い出してください。これらのベクトルが垂直の場合は消えます。 
このように: 
- ベクトルを見つける
、ポイントA 1 、A 2 、B 1 、B 2






- ベクトルを見つける
、ポイントC 1 、C 2 、C 3 、C 4






- 楕円を描くには、2つのベジェ曲線が必要であることを思い出してください。
- 1stには開始点B 1があり 、終了点B 2が点A 1を通過します
- 2番目には開始点B 2 、終了点B 1があり、点A 2を通過します
ベジェ曲線を作成するには、制御点が必要であることも思い出してください。 考え直すことなく、まず楕円が内接する長方形の頂点を置き換えました。 この解決策は間違いであることが判明しました。ベジェ曲線の作成を検討すると、2つの制御点を接続するセグメントに触れないことがわかります。
ベジエ曲線(曲線)が制御点間のセグメントに最も近くなる点でのベジエ曲線の構築の瞬間を示してみましょう。 この場合、次のようになります。

図から、この点(A 1 )から制御点(C 1 、C 2 )間のセグメントまでの距離は、目的の楕円(O)の中心と同じセグメント(C 1 、C 2 )間の距離の1/4になることが明らかです。あります:

- xでOAを表します。 方程式を解く



したがって、必要なパラメーターで楕円を取得するには、ベクトルを乗算する必要があります
パラメーターごと
その後、パラグラフ1〜4で説明した計算に戻ります。 その結果、目的の形状を一緒に表す2つのベジェ曲線を作成するためのポイントのセット( B 1 、C 1 、C 2 、B 2およびB 2 、C 3 、C 4 、B 1 )を取得します。
実際に
デモとコード:
function drawEllipse(ctx, coords, sizes, vector) { var vLen = Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]);

更新しました。 コメントを確認した後、パラメトリック方程式を使用して楕円を描画する機能を作成しましたが、ベジェ曲線を使用して取得した図形が楕円と正確に一致しないことがわかりました。 図形のオーバーレイでは、ベジェ曲線によって描かれたオブジェクト(赤)が通常の楕円(青)よりも広いことがあります。 これは、重なり合う形状の
デモです 。

function drawEllipseParam(ctx, coords, sizes, angle, segments) { ctx.save(); ctx.translate(coords[0], coords[1]); ctx.rotate(angle); ctx.beginPath(); var x, y, firstTime=true; var dt = 2*Math.PI/segments; for(var t=0; t<2*Math.PI; t+=dt) { x = sizes[0]*Math.cos(t); y = sizes[1]*Math.sin(t); if(firstTime) { firstTime = false; ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } } ctx.strokeStyle = 'blue'; ctx.stroke(); ctx.closePath(); ctx.restore(); }
更新しました。 コメントは、斜めの楕円を描くためのよりネイティブでシンプルな方法を提案しました(
subzeyに感謝)。 迷子にならないようにここを離れます。 これが
デモです。
function drawEllipse(ctx, coords, sizes, angle) { ctx.beginPath(); ctx.save();