web-dev-qa-db-ja.com

SVG円弧パスを使用した円の描画

簡単な質問:SVGパスを使用すると、99.99%の円を描画して表示できますが、99.99999999%の円の場合、円は表示されません。どうすれば修正できますか?

次のSVGパスは、円の99.99%を描画できます:( http://jsfiddle.net/DFhUF/1381/ で試して、4つの円弧または2つの円弧のみが表示されるかどうかを確認しますが、 IEの場合、SVGではなくVMLでレンダリングされますが、同様の問題があります)

M 100 100 a 50 50 0 1 0 0.00001 0

しかし、円の99.99999999%の場合、何も表示されませんか?

M 100 100 a 50 50 0 1 0 0.00000001 0    

そして、それは100%の円でも同じです(それはまだ円弧です、そうではなく、単なる完全な円弧です)

M 100 100 a 50 50 0 1 0 0 0 

どうすれば修正できますか?その理由は、関数を使用して円弧の割合を描画し、99.9999%または100%の円弧を「特殊な場合」に使用してcircle関数を使用する必要がある場合、それは一種のばかげたことです。

繰り返しますが、RaphaelJSを使用したjsfiddleのテストケースは http://jsfiddle.net/DFhUF/1381/ にあります。
(およびIE 8のVMLの場合、2番目の円も表示されません... 0.01に変更する必要があります)


更新:

これは、システムでスコアの円弧をレンダリングしているため、3.3ポイントが円の3分の1を取得するためです。 0.5は円の半分を取得し、9.9ポイントは円の99%を取得します。しかし、システムに9.99のスコアがある場合はどうでしょうか?円の99.999%に近いかどうかを確認し、それに応じてarc関数またはcircle関数を使用する必要がありますか?それでは、9.9987のスコアはどうですか?どちらを使用しますか?どのような種類のスコアが「完全な円」にマッピングされ、円関数に切り替わり、それが円の「特定の99.9%」または9.9987スコアの場合、アーク関数を使用する必要があるのはばかげている。

136

XAMLのアークでも同じです。 Zで99.99%の円弧を閉じると、円ができます!

33
Todd Main

ゲームが少し遅れていることは知っていますが、この質問を覚えたのは、それが新しくて、同様のディレンマがあったときのことです。誰かがまだ探しているなら、誤って「正しい」解決策を見つけました。

<path 
    d="
    M cx cy
    m -r, 0
    a r,r 0 1,0 (r * 2),0
    a r,r 0 1,0 -(r * 2),0
    "
/>

言い換えれば、これ:

<circle cx="100" cy="100" r="75" />

これでパスとして実現できます:

  <path 
        d="
        M 100, 100
        m -75, 0
        a 75,75 0 1,0 150,0
        a 75,75 0 1,0 -150,0
        "
  />

トリックは、2つのアークを使用することです。2番目のアークは最初のアークが中断したところからピックアップし、負の直径を使用して元のアーク開始点に戻ります。

1つの円弧で完全な円として行うことができない理由は(そして私は推測しているだけです)それはあなたがそれ自身(例えば150,​​150)からそれ自体(150,150)に円弧を描くようにそれを伝えるためです「ああ、私はすでにそこにいます、アークは必要ありません!」.

私が提供しているソリューションの利点は次のとおりです。

  1. 円から直接パスに簡単に変換できます。
  2. 2つの円弧線に重なりはありません(マーカーやパターンなどを使用している場合に問題が発生する可能性があります)。 2つの部分に分けられていますが、きれいな連続線です。

テキストパスが図形を受け入れることを許可するだけであれば、これは問題になりません。しかし、円のような形状要素には技術的に「開始」点がないため、彼らはその解決策を避けていると思います。

jsfiddleデモ: http://jsfiddle.net/crazytonyi/mNt2g/

更新:

textPath参照のパスを使用しており、テキストを円弧の外側のエッジにレンダリングする場合は、まったく同じ方法を使用しますが、sweep-flagを0から1に変更して、パスの外側を内側ではなく表面として扱います(1,0は中心に座って自分の周りに円を描くと考え、1,1は半径距離で中心を歩いていると考えます。助けがあれば、チョークを横にドラッグします)。上記のコードを次に示しますが、変更があります。

<path 
    d="
    M cx cy
    m -r, 0
    a r,r 0 1,1 (r * 2),0
    a r,r 0 1,1 -(r * 2),0
    "
/>
387
Anthony

アンソニーのソリューションに関して、パスを取得する関数は次のとおりです。

function circlePath(cx, cy, r){
    return 'M '+cx+' '+cy+' m -'+r+', 0 a '+r+','+r+' 0 1,0 '+(r*2)+',0 a '+r+','+r+' 0 1,0 -'+(r*2)+',0';
}
15

まったく異なるアプローチ:

パスをいじってsvgでアークを指定する代わりに、擬似コードでcircle要素を取得してstroke-dasharrayを指定することもできます。

with $score between 0..1, and pi = 3.141592653589793238

$length = $score * 2 * pi * $r
$max = 7 * $r  (i.e. well above 2*pi*r)

<circle r="$r" stroke-dasharray="$length $max" />

そのシンプルさは、複数のアークパス方式に対する主な利点です(たとえば、スクリプトを作成するときに、1つの値のみをプラグインし、アークの長さについては完了です)

円弧は右端のポイントから始まり、回転変換を使用して移動できます。

注:Firefoxには、90度以上の回転が無視されるという奇妙なバグがあります。したがって、上からアークを開始するには、次を使用します。

<circle r="$r" transform="rotate(-89.9)" stroke-dasharray="$length $max" />
10
mvds

Adobe IllustratorはSVGのようなベジェ曲線を使用し、円の場合は4つのポイントを作成します。 2つの 楕円弧コマンド ...で円を作成できますが、SVGの円では<circle />を使用します:)

5
Phrogz

アンソニーとアントンの答えに基づいて、生成された円を全体的な外観に影響を与えずに回転させる機能を組み込みました。これは、アニメーションのパスを使用していて、アニメーションの開始位置を制御する必要がある場合に便利です。

function(cx, cy, r, deg){
    var theta = deg*Math.PI/180,
        dx = r*Math.cos(theta),
        dy = -r*Math.sin(theta);
    return "M "+cx+" "+cy+"m "+dx+","+dy+"a "+r+","+r+" 0 1,0 "+-2*dx+","+-2*dy+"a "+r+","+r+" 0 1,0 "+2*dx+","+2*dy;
}
3
rfoo

2つのarcコマンドを使用して完全な円を描くことをお勧めします。

通常、楕円または円要素を使用して完全な円を描きます。

3
cuixiping

関数として書かれており、次のようになります。

function getPath(cx,cy,r){
  return "M" + cx + "," + cy + "m" + (-r) + ",0a" + r + "," + r + " 0 1,0 " + (r * 2) + ",0a" + r + "," + r + " 0 1,0 " + (-r * 2) + ",0";
}
2
Harry Stevens

これらの答えは非常に複雑です。

2つの円弧を作成したり、異なる座標系に変換したりせずにこれを行う簡単な方法。

これは、キャンバス領域の幅がwおよび高さhであることを前提としています。

`M${w*0.5 + radius},${h*0.5}
 A${radius} ${radius} 0 1 0 ${w*0.5 + radius} ${h*0.5001}`

「長い円弧」フラグを使用するだけで、完全なフラグが埋められます。次に、円弧を99.9999%の完全な円にします。視覚的には同じです。スイープフラグを避けるには、円の右端のポイント(中心から直接水平に1つの半径)で円を開始するだけです。

パス変換の楕円属性を探していた私のような人のために:

const ellipseAttrsToPath = (rx,cx,ry,cy) =>
`M${cx-rx},${cy}a${rx},${ry} 0 1,0 ${rx*2},0a${rx},${ry} 0 1,0 -${rx*2},0`
1
yogi

別の方法は、2つの立方ベジェ曲線を使用することです。これは、svg arcパラメーターを認識しない pocketSVG を使用するiOSユーザー向けです。

C x1 y1、x2 y2、x y(またはc dx1 dy1、dx2 dy2、dx dy)

Cubic Bezier curve

ここの最後の座標セット(x、y)は、ラインを終了する場所です。他の2つはコントロールポイントです。 (x1、y1)は曲線の開始点の制御点であり、(x2、y2)は曲線の終点の制御点です。

<path d="M25,0 C60,0, 60,50, 25,50 C-10,50, -10,0, 25,0" />
0
ha100

ここでそれを行うためにjsfiddleを作成しました:

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;

return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}

function describeArc(x, y, radius, startAngle, endAngle){

var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);

var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

var d = [
    "M", start.x, start.y, 
    "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
].join(" ");

return d;       
}
console.log(describeArc(255,255,220,134,136))

リンク

あなたがする必要があるのは、console.logの入力を変更し、コンソールで結果を取得することです

0
javad bat