4

SVG 仕様のARCTOは、 Canvasのものとはかなり異なります。SVG仕様に従ってデータを取得するユースケースがありますが、キャンバスに描画する必要があります。

これを試しましたが、ジオメトリが弱いと思います。助けていただけますか?

4

5 に答える 5

3

svg楕円とキャンバスアークの違いは、svgには2つの半径があり、arcToには1つの半径しかないことです。次に、キャンバス内の特定の角度で円弧を回転させる必要もあります。2つの半径をエミュレートするには、指定された座標で最小の半径を持つ円弧を作成する必要があります。次に、このアークを係数(rx / ry)を使用して特定の方向にスケーリングする必要があります。そして今、あなたは回転するだけでよいのです。しかし、このアプローチでは、楕円のどの部分を表示するかを判断するのは非常に困難です。これは、svg仕様のlarge-arc-flagとsweep-flagに依存するためです。もう1つの問題は、(svg仕様からの)終了座標によってアークを制限することです。したがって、arcToを使用すると、最大で楕円の半分を作成できると思います。

楕円上に3つの制御点の座標がある場合は、bezierCurveTo(x0、y0、x1、y1、x2、y2)を使用して楕円の一部を描画することもできます。このアプローチを使用すると、楕円の任意のセグメントを作成できます。もちろん、PIを超えるセグメントの場合、少なくとも2つの曲線が必要になります

あなたが持っているSVG仕様から(rx ry x-axis-rotation large-arc-flag swap-flag xy)。したがって、サンプルパスは次のようになります。

  M100,100 a25,50 -30 0,1 50,-25

ここでは、ベジェ曲線の描画方法を見つけることができます。

これで、コンテキストポイント(100,100)とエンドポイント(100 + 50,100-25)ができました。-30度に回転する前に、コントロールポイントを計算する必要があります。

ここに私のために働く例があります:

$(document).ready(function(){
        var startX = 100;
        var startY = 100;
        var dX = 50;
        var dY = -25;
        var angle = -30;
        var rx = 25;
        var ry = 50;
        var svg = Raphael($('#svg')[0], 200, 200);

        var path = "M" +startX + "," + startY + " a" + rx + "," + ry + " " + angle + " 0,1" + " " + dX + "," +dY;
        svg.path(path).attr({"stroke-width" : 2, "stroke" : "#FFFFFF"});

        var kappa = .5522848,
        ox = rx*kappa,
        oy = ry*kappa,
        xm = startX + rx,       // x-middle
        ym = startY + ry;       // y-middle
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        ctx.moveTo(startX,startY);
        ctx.bezierCurveTo(startX, startY - oy, startX + ox, startY - ry, startX + rx, startY - ry);
        ctx.bezierCurveTo(startX + rx + ox, startY - ry, startX + 2*rx, startY - oy, startX + dX, startY + dY);
        ctx.stroke();
    });

マークアップは単純です:

<div id="svg" style="border: 1px solid black;position : absolute;top : 50px;left : 50px;"></div>
<canvas id="canvas" width="200px" height="200px" style="border: 1px solid black;position : absolute;top : 300px;left : 50px;"></canvas>

コントロールポイントを-30度回転させなかったため、曲線は似ていません。しかし、私はそれがあなたがしなければならない唯一のことだと信じています。角度=0とすると、似たようなものになるからです。この記事を使用して、回転の数学を取得できます。

PS:私はこの答えからコードの一部を取りました

于 2011-07-18T06:03:01.227 に答える
1

「M100,100 a25,50 -30 0,1 50,-25」をキャンバスにマップしようとするときは、私の関数を使用してください。確かに、円弧を念頭に置いてこれを書きました。

楕円 (100,100,50,-25,50,false);

function ellipse(x1, y1, x2, y2, radius, clockwise) {

var cBx = (x1 + x2) / 2;    //get point between xy1 and xy2
var cBy = (y1 + y2) / 2;
var aB = Math.atan2(y1 - y2, x1 - x2);  //get angle to bulge point in radians
if (clockwise) { aB += (90 * (Math.PI / 180)); }
else { aB -= (90 * (Math.PI / 180)); }
var op_side = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) / 2;
var adj_side = Math.sqrt(Math.pow(radius, 2) - Math.pow(op_side, 2));

if (isNaN(adj_side)) {
    adj_side = Math.sqrt(Math.pow(op_side, 2) - Math.pow(radius, 2));
}

var Cx = cBx + (adj_side * Math.cos(aB));            
var Cy = cBy + (adj_side * Math.sin(aB));
var startA = Math.atan2(y1 - Cy, x1 - Cx);       //get start/end angles in radians
var endA = Math.atan2(y2 - Cy, x2 - Cx);
var mid = (startA + endA) / 2;
var Mx = Cx + (radius * Math.cos(mid));
var My = Cy + (radius * Math.sin(mid));
context.arc(Cx, Cy, radius, startA, endA, clockwise);
}
于 2013-03-15T04:02:19.700 に答える