Нарисуйте кривую Безье SVG
У меня есть массив контрольных точек, представляющих кривую Безье высокого порядка.
Как я могу нарисовать эту кривую, используя один SVG-путь?
UPD:
Например, у меня есть набор точек: (x1, y1) (x2, y2) (x3, y3) (x4, y4) (x5, y5).
Как будет выглядеть SVG-путь в терминах C
, S
, Q
или T
?
UPD 2: РЕШЕНИЕ
Я задал этот вопрос, чтобы изобразить путь объекта, анимированный с помощью TweenMax .
Позже я получил ответ на форумеGreenSock .
Вот примерCodePen .
2 ответа:
Короткий ответ: вы не можете.
SVG имеет только квадратичные (2-го порядка) и кубические кривые (3-го порядка), тогда как кривая, которую вы показываете, является Квартовой (4-го порядка). SVG не имеет общей инструкции рисования" N term Bezier", поэтому вам придется пойти на компромисс.
Некоторые варианты:
- преобразуйте кривую в (ряд) кубических кривых и визуализируйте их вместо этого. Это довольно сложная проблема и не очень рекомендуется.
- примерьте свою кривую в достаточном количестве точек, таких как что многоугольник, проходящий через эти точки, выглядит как кривая при разрешении и увеличении, люди будут смотреть на него. Это легко сделать, но, конечно, у вас больше нет "кривой", теперь у вас есть многоугольник.
- Как и выше, но меньше точек, а затем вычислить последовательность кривых Catmull-Rom, которая проходит через эти точки, а затем преобразовать эти кривые CR в кубические Безье (они являются одним и тем же типом функции и могут быть преобразованы 1:1 из одной в другую). Это лучше, чем 2, потому что у вас есть кривой, но она не может смотреть совсем же, как и оригинал. Конечно, чем больше очков вы используете, тем лучше будет результат.
- используйте холст, чтобы нарисовать кривую Безье N-й степени, построить изображение из результата с помощью функции
toDataURL
, а затем загрузить это изображение как изображение в SVG. Это будет работать отлично, но если вы используете созданный стиль пути SVG, то создание холста в том же стиле может оказаться непростой задачей.- Этот список может быть очень длинным, так что давайте пока остановимся здесь.
Итог: Если вам нужно показать кривые Безье более высокого порядка, SVG не является подходящей технологией для использования (я бы рекомендовал просто делать анимацию с использованием холста, или еще лучше, что-то вроде d3.js или бумага.js . Вероятно, последнее).
И если вы в конечном итоге сворачиваете свой собственный, функция выборки смехотворно проста. Кривые являются параметрическими, управляемыми значением
t
, которое выполняется от 0 до 1 (включительно), и могут быть записывается как вложенная линейная интерполяция:getCurvePoint(t, points) { if (points.length === 1) return points[0]; var newpoints = []; for(var i=0,j=1; j<points.length; i++,j++) { newpoints[i] = lerp2d(t, points[i], points[j]); } return getCurvePoint(t,newpoints); }
С функцией
lerp
, являющейся стандартной линейной интерполяционной функцией:lerp(ratio, start, end) { return ratio*start + (1-ratio)*end; } lerp2d(ratio, start, end) { return { x: lerp(ratio, start.x, end.x), y: lerp(ratio, start.y, end.y) }; }
И простой пример jsbin: http://jsbin.com/pesutibefu/edit?html,js, вывод с использованием точек
var points = [ {x:50, y:100}, {x:50, y:250}, {x:210, y:250}, {x:250, y:50}, {x:380, y:150} ];
Дает нам:
Хотя и бумага.JS sketch будет проще работать, если вам нужны анимированные красивые контуры, с перетаскиваемыми контрольными точками и т. д.
SVG не поддерживает кривые Безье, кроме квадратичных и кубических. Таким образом, нет представления в терминах команд(C, S, Q или T).
Кривую Безье можно определить двумя способами: с помощью команды "C" для кубической или с помощью команды "Q" для квадратичной. Те команды имеют фиксированную длину параметров, которая является 4 для квадратичной и 6 для кубической, поэтому пример строки SVG будет выглядеть как "Q 150,-300 300,0" Вы можете увидеть строку SVG вот так "Q 150,-300 300,0 50,150 100,200" но это всего лишь две четырехугольные кривые одна за другой, и число параметров всегда будет кратно 4 для "Q" и кратно 6 для "C".M = moveto
L = lineto
H = горизонтальная линия
V = вертикальная линия
C = curveto
S = гладкая кривизна
Q = квадратичная кривая Безье
T = гладкая квадратичная кривизна Безье
А = эллиптическая Дуга
Z = closepathИмеет представление в виде JavaScript или фактически в любом другом стандартном API (.NET Drawing, Core Graphics, Android Canvas), но во всех них нет никакого метода для чего-либо, кроме кубического или квадратичного. Кроме того, по своему опыту я никогда не видел приложения для рисования, которое имеет возможность рисовать кривую Безье более высокого порядка. Поэтому ваш лучший вариант-упростить кривую высокого порядка до Q или C.