Разница между svg ellipse и canvas arc заключается в том, что у вас есть 2 радиуса в svg и только один в arcTo. Затем вам также нужно повернуть дугу на определенный угол на холсте. Чтобы эмулировать 2 радиуса, необходимо создать дугу с заданными координатами, имеющими наименьший радиус. Затем вам нужно масштабировать эту дугу в определенном направлении с коэффициентом (rx / ry). И теперь вам нужно только вращаться. Но в этом подходе действительно трудно определить, какую часть эллипса вы хотите показать, потому что это зависит от флага большой дуги и флага развертки в спецификации svg. Другая проблема - ограничить вашу дугу конечными координатами (из спецификации SVG). Так что с помощью arcTo вы можете построить максимум половину эллипса, я думаю.
Вы также можете использовать bezierCurveTo (x0, y0, x1, y1, x2, y2), чтобы нарисовать часть эллипса, если у вас есть координаты 3 контрольных точек на вашем эллипсе. При таком подходе вы можете построить любой сегмент эллипса. Конечно, для сегментов больше чем PI вам понадобятся как минимум две кривые
Из имеющейся у вас спецификации SVG (rx или x-ось-вращение, флаг большой дуги, флаг-развертка x y). Таким образом, примерный путь будет таким:
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: я взял некоторые части кода из этого ответа