2013-04-19 6 views
1

Я пытаюсь нарисовать кривую Безье окружающей эллипс с заданным запасом:Рисунок часть эллипса программно с Безье или эллиптической траектории - SVG и Raphaël.js

Bezier path surrounding an ellipse

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

На данный момент я сделал эту функцию:

function bezierPathTopRounded(ellipse, margin) { 
    var box = ellipse.paper.getBBox(); 

    var leftX = box.x - margin; 

    var rightX = box.x + margin + box.width; 

    var y = box.y + box.height/2 - margin; 

    var p = "M "+ leftX + ", "+ y 
    + " C " //could be relative too 
    + (box.x - margin + (box.width/15) ) + ", " + (box.y + margin - (box.height/4.5) ) + " " 
    + (box.x + margin + box.width - (box.width/15) ) + ", " + (box.y + margin - (box.height/4.5)) + " " 
    + rightX +", " + y; 

    return p; 
} 

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

  • box.width/15
  • box.height/4,5

Существует fiddle with this example.

Я прочитал это stackoverflow question и я попробовал то же самое на моем примере, но до сих пор не могу понять, простое решение, оно остается случайным ...

Редактировать

Теперь я м, пытаясь с эллиптическим A гсом, результат worser чем с путем Безье:

Elliptical Arc test

Существует функцию я использую. Если я удаляю поле, он точно соответствует моему эллипсу ... Наконец, это вопрос, как я могу следовать за эллипсом с запасом?

function borderPath(ellipse, margin, flag) { 
    var flag = flag == undefined ? 1 : 0; 

    var box = ellipse.paper.getBBox(); 

    var leftX = box.x - margin; 

    var rightX = box.x + margin + box.width; 

    var y = box.y + box.height/2; 
    y += (flag == 1) ? -margin : margin; 

    var rx = box.width/2 + margin; 
    var ry = box.height/2; 

    var p = "M "+ leftX + ", "+ y 
    + " A " 
    + rx + " " + ry 
    + " 0 0 "+ flag +" " 
    + rightX +", " + y; 

    return p; 
} 

См. updated fiddle here.

Действительно извините за ужасные цвета, это, например, цель.

+0

Почему Безье? Почему бы не провести еще один частичный эллипс соответствующего размера/позиции? –

+0

Вы meen с эллиптической дугой? Я пробовал это раньше, но это было невозможно из-за того, что он не был совершенным эллипсом. И мне нужно, чтобы это был путь, поэтому я могу нарисовать эту конкретную строку. – soyuka

+0

Да, я имею в виду эллиптическую дугу, хотя вижу, что концентрические эллипсы не могут дать эффект, который вы ищете. Сказав, что я думаю, что кривая Безье будет только приближением. Как вы вывели 'box.width/15' и' box.height/4.5'? Разве это не вопрос обобщения математики? –

ответ

1

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

Вот функция:

function borderPath(ellipse, flag) { 
    var flag = flag == undefined ? 1 : flag; 

    var box = ellipse.paper.getBBox(); 

    var leftX = box.x; 

    var rightX = box.x + box.width; 

    var y = box.y + box.height/2; 

    var rx = box.width/2; 
    var ry = box.height/2; 

    var p = "M "+ leftX + ", "+ y 
    + " A " 
    + rx + " " + ry 
    + " 0 0 "+ flag +" " 
    + rightX +", " + y; 

    return p; 
} 
2

Если вы хотите сделать это с помощью кривых Безье, вам придется решить, как «неправильно» вы хотите, чтобы он выглядел. Кривые Безье не могут представлять круговые (а также удлиненные, эллиптические) кривые, они могут только стать очень близкими, точно так же, как многоугольник, с большей точностью, используя меньшее количество секций.

я описываю как круг приближения и кривой компенсируя с помощью кривых Безье в моей грунтовке на кривых Безье, http://pomax.github.io/bezierinfo/#circles_cubic и http://pomax.github.io/bezierinfo/#offsetting соответственно, но если вы кодирование это с нуля особенно компенсирующим будет излишним, если вам это нужно только для чего вы описываете в своем примере.

Вместо этого я рекомендовал бы запустить Inkscape или Illustrator, включив наложение сетки и нарисовать кривую безье вокруг вашего эллипса. Сделайте это хорошо, затем проверьте, что такое координаты, и используйте это как достаточно надежную информацию для реализации в вашей программе холста. Вы, вероятно, не нуждаетесь в математически жесткой правильности, если люди не идут «это выглядит неправильно», вы должны быть в порядке.

+0

Хорошие статьи, которые вы получили там! Я согласен с тем, что они не могут быть совершенно правы, но на моем примере это выглядит не так «неправильно», не так ли? Я не могу сделать их с Inkscape и т. Д., Потому что я хочу оживить их в соответствии с эллипсом. Мое решение до сих пор имеет две разные функции для пути (начало, конец). Теперь, если бы я хотел иметь «идеальные» кривые, следует ли использовать эллиптические дуги? - что тоже будет неправильно, потому что оно сокращено по краю. – soyuka

+0

Использование эллиптической дуги, вероятно, будет достаточно для вас, если вы смещаете оба радиуса на ту же сумму. Итак, если ваш эллипс (x, y, r1, r2), и вы хотите смещение над половиной эллипса, скажем, 10px, вы должны использовать arc (x, y, r1 + 10, r2 + 10, pi, 2 * pi), причем последние два указывают угол начала и конца вашей дуги. Проблема здесь в том, что если вы используете Canvas2D, единственной дугой, доступной на данный момент, является дуга окружности. Команда эллиптической дуги («эллипс»), наконец, находится в обновленном проекте (я один из тех, кто его просил, очень рад, что он был добавлен сейчас), но пока не поддерживается –

+0

Я использую Рафаэль (svg no canvas поэтому 'A' path -' rx ry x-axis-rotation большой-флаговый флаг swy-flag xy'), но я попробую найти способ с этим сообщением. – soyuka

0

Использование кривых Безье для рисования эллиптического пути может вызвать головные боли. Как вы сказали в комментарии, вы используете дугу пути, которая хорошо работает с RaphaelJS.

Документацию обо всех значениях, которые она ожидает, особенно флаги, можно найти по адресу http://www.svgbasics.com/arcs.html.

+0

Я знаю все это, спасибо, но с Безье он работает лучше – soyuka