Круговой рисунок с дугой SVG

Короткий вопрос: используя путь SVG, мы можем нарисовать 99,99% круга, и он появляется, но если он равен 99,999999999% круга, то круг не будет отображаться. Как это можно исправить?

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

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%, чтобы использовать функцию круга, это было бы глупо.

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


Обновить:

Это потому, что я выставляю дугу для оценки в нашей системе, поэтому 3,3 балла получают 1/3 круга. 0,5 получает половину круга, а 9,9 балла - 99% круга. Но что, если в нашей системе есть 9,99 баллов? Нужно ли проверять, находится ли он близко к 99,999% круга, и использовать функцию arc или функцию circle соответственно? Тогда как насчет 9.987? Какой использовать? Смешно знать, какие оценки будут отображаться в "слишком полный круг" и переключаться на функцию круга, а когда это "определенный 99,9%" от круга или 9,9997, тогда использовать функцию дуги,

Ответ 1

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

Ответ 2

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

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

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

Причина, по которой она не может быть выполнена как полный круг в одной дуге (и я просто размышляю), заключается в том, что вы будете говорить ей, чтобы рисовать дугу от себя (скажем 150 150) к себе (150,150), который он отображает как "о, я уже там, никакой дуги не нужно!".

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

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

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

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

Ответ 3

В отношении решения Anthonys, вот функция для получения пути:

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

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`

Ответ 10

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

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

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

Ответ 11

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

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

Кубическая кривая Безье

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

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

Ответ 12

я сделал 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 и получить результат в консоли

Ответ 13

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

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