Ответ 1
Короткий ответ: вы не можете.
SVG только построил квадратные (2-й порядок) и кубические кривые (3-й порядок), тогда как кривая, которую вы показываете, является Quartic (4-й порядок). У SVG нет общей инструкции рисования "N term Bezier", поэтому вам придется идти на компромисс здесь.
Некоторые параметры:
- преобразуем кривую в (кубические) кривые и сделаем их. Это довольно сложная проблема и не рекомендуется.
- примерьте свою кривую в достаточном количестве точек, чтобы полигон через эти точки выглядел как кривая с разрешением и уровнем масштабирования, на которые люди будут смотреть. Это легко сделать, но, конечно, у вас больше нет "кривой", теперь у вас есть многоугольник.
- как указано выше, но меньше точек, а затем вычислить последовательность кривой Катмулла-Рома, которая проходит через эти точки, затем преобразует эти кривые CR в кубический Bezier (они являются одним и тем же типом функции и могут быть преобразованы 1:1 от одного к другому). Это лучше, чем 2, потому что у вас есть кривая, но она может выглядеть не так, как оригинал. Конечно, чем больше очков вы используете, тем лучше результат.
- используйте холст, чтобы нарисовать кривую Безье кривой Nth, постройте изображение из результата с помощью функции
toDataURL
, а затем загрузите это изображение в качестве изображения в SVG. Это будет отлично работать, но если вы используете созданный стиль SVG-пути, создание холста с помощью одного и того же стиля может стать проблемой. - этот список может занять очень много времени, поэтому отпустите здесь.
В нижней строке: если вам нужно показать кривые Безье более высокого порядка, SVG не является подходящей технологией для использования (я бы рекомендовал просто делать вашу анимацию с помощью холста, или еще лучше, что-то вроде d3.js или paper.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,output с использованием точек
var points = [
{x:50, y:100},
{x:50, y:250},
{x:210, y:250},
{x:250, y:50},
{x:380, y:150}
];
дает нам:
Хотя скетч Paper.js будет работать легче, если вам нужны анимированные красивые пути, с перетаскиваемыми контрольными точками и т.д.