Рисование круга с дуговым путем SVG

следующий путь SVG может нарисовать 99,99% круга: (попробуйте на http://jsfiddle.net/DFhUF/46/ и посмотрите, видите ли вы 4 дуги или только 2, но обратите внимание, что если это IE, он отображается в VML, а не SVG, но имеет аналогичную проблему)

M 100 100 a 50 50 0 1 0 0.00001 0

но когда это 99.9999999999% круга, то ничего не будет отображаться вообще?

M 100 800 a 50 50 0 1 0 0.00000001 0    

и это то же самое со 100% круга (это все еще дуга, не так ли, просто очень полная arc)

M 100 800 a 50 50 0 1 0 0 0 

как это можно исправить? Причина в том, что я использую функцию для рисования процента дуги, и если мне нужно "особый случай" 99,9999% или 100% дуги для использования функции круга, это было бы глупо.

опять же, тестовый пример на jsfiddle, используя RaphaelJS на http://jsfiddle.net/DFhUF/46/
(и если это VML на IE 8, даже второй круг не будет отображаться... вы должны изменить его на 0.01)


обновление:

это потому, что я рендеринг дуги для оценки в нашей системе, поэтому 3.3 точки получают 1/3 круга. 0.5 получает половину круга, а 9.9 очков-99% круга. Но что, если в нашей системе есть оценки, которые составляют 9,99? Должен ли я проверить, близок ли он к 99,999% круга, и использовать или

13 ответов


то же самое для дуги XAML. Просто закройте дугу 99.99% с помощью Z и у вас есть круг!


Я знаю, что это немного поздно в игре, но я вспомнил этот вопрос, когда он был новым, и у меня была аналогичная диллемма, и я случайно нашел "правильное" решение, если кто-то все еще ищет его:

<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
        "
  />

трюк состоит в том, чтобы иметь две дуги, вторая поднимает, где первая остановилась, и использует отрицательный диаметр, чтобы вернуться к исходной дуге начальная точка.

преимущества решения, которое я предлагаю:

  1. это легко перевести из круга непосредственно в путь, и
  2. в двух дуговых линиях нет перекрытия (которое может вызвать проблемы, если вы используете маркеры или узоры и т. д.). Это чистая непрерывная линия, хотя и разделенная на две части.

ничего из этого не имело бы значения, если бы они просто позволяли textpaths принимать формы. Но я думаю, что они избегают этого решения, поскольку элементы формы, такие как круг, технически не имеют "начальной" точки.

jsfiddle demo:http://jsfiddle.net/crazytonyi/mNt2g/

обновление:

если вы используете путь к textPath ссылка и вы хотите, чтобы текст отображался на внешнем краю дуги, вы бы использовали тот же самый метод, но изменили флаг развертки с 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
    "
/>

обратитесь к решению Энтони вот функция, чтобы получить путь:

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';
}

совершенно другой подход:

вместо того, чтобы возиться с путями для указания дуги в svg, вы также можете взять элемент circle и указать штрих-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" />

его простота является основным преимуществом по сравнению с методом множественной дуги пути (например, при написании сценариев вы подключаете только одно значение, и вы сделали для любой длины дуги)

дуга начинается в самой правой точке и может быть сдвинута с помощью поворота преобразиться.

Примечание: Firefox имеет нечетную ошибку, где вращения более 90 градусов или более игнорируются. Итак, чтобы начать дугу сверху, используйте:

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

Adobe Illustrator использует кривые Безье, такие как SVG, и для кругов он создает четыре точки. Вы можете создать круг с двумя команды эллиптической дуги...но тогда для круга в SVG я бы использовал <circle /> :)


Это хорошая идея, что с помощью команды две дуги, чтобы нарисовать полный круг.

обычно я использую элемент эллипса или круга для рисования полного круга.


записывается как функция, это выглядит так:

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";
}

основываясь на ответах Энтони и Антона, я включил способность вращать сгенерированный круг, не влияя на его общий внешний вид. Это полезно, если вы используете путь для анимации и вам нужно контролировать, где он начинается.

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;
}

для таких, как я, которые искали атрибуты эллипса для преобразования пути:

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`

Я сделал 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))

ссылке

все, что вам нужно сделать, это изменить ввода консоли.войдите и получите результат в консоли


другой способ-использовать две кубические кривые Безье. Это для людей iOS, использующих pocketSVG который не распознает параметр svg arc.

C x1 y1, x2 y2, x y (или C dx1 dy1, dx2 dy2, dx dy)

Cubic Bezier curve

последний набор координат здесь (x, y), где вы хотите, чтобы линия заканчивалась. Два других-контрольные точки. (x1, y1) является контрольной точкой для начала вашей кривой и (x2,y2) для конечной точки вашего кривая.

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

эти ответы слишком сложные.

более простой способ сделать это без создания двух дуг или преобразования в различных системах координат..

это предполагает, что ваша область холста имеет ширину 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% полным кругом. Визуально это то же самое. Избегайте флага развертки, просто начиная круг в самой правой точке круга (один радиус непосредственно горизонтальный от центра).


эти примеры слишком сложны!!!

просто сделайте это с литералами шаблонов es6.

более простой способ сделать это без создания двух дуг..

предполагается, что область холста имеет ширину 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% полным кругом. Визуально это то же самое. Избегайте флага развертки, просто начиная круг в самой правой точке круга (один радиус непосредственно горизонтальный от центра).