Применение закругленных углов к дорожкам/полигонам
Я собираю информацию о проекте, который должен начаться через несколько недель.
Этот проект содержит инструмент рисования на основе браузера, в котором пользователи могут добавлять предопределенные формы или сами формировать фигуры. Формы должны выбираться, свободно масштабироваться и поворачиваться с помощью Illustrator-подобного transformtool (ручки).
Предопределенные формы, которые мы имеем в виду: прямоугольники, эллипсы, полуэллипсы и (равнобедренные) треугольники.
До сих пор так хорошо, для достижения этого я думал о RaphaelJS или FabricJS, но... Каждая фигура (полигон/путь) должна быть нарисована с помощью определенного угла. И cornerradius должен поддерживаться при масштабировании, поэтому никаких искажений не возникает. Пользователь может указать округление по вводу.
Есть несколько препятствий/вопросов:
- Есть ли какая-то унифицированная математическая формула, чтобы применить угловую форму к фигурам, которые я упомянул? Или каждая форма должна рассматриваться как сам мини-проект? Я хочу вернуть его как путь или поли, поэтому его можно нарисовать с помощью SVG или холста.
- Каждая операция масштабирования или поворота, перетаскивая манипуляторы преобразования, приведет к (массивным) вычислениям для получения обновленной формы, я думаю. Прямоугольники являются самыми легкими для достижения и, кроме эллипсов, все остальные формы будут намного сложнее вычислять. Есть ли способ ускорить процесс?
Я нашел сайт, на котором пользователи могут рисовать блок-схемы и применять угловую форму почти на всех фигурах. Он работает так гладко, я не могу прибить, как они это сделали.
Ссылка: https://www.lucidchart.com/ (кнопка "Попробовать" )
В настоящее время я немного невежественный, я думаю, что он посредственный в математике. Возможно, кто-то может подтолкнуть меня в правильном направлении и поделиться некоторыми впечатлениями?
Спасибо заранее.
BTW. Производительность является ключевым в этом проекте. Вывод чертежа должен быть форматом SVG.
Ответы
Ответ 1
У меня возникла аналогичная проблема, и я не смог найти простое решение. В конце концов я написал довольно общую функцию округления углов, основанную на работе Adobe Illustrator. Он использует кривые Безье вместо дуг, но я думаю, что результат довольно приличный.
Он поддерживает округление с радиусом, заданным в координатном пространстве изображения SVG, или как часть расстояния между углом и его соседями.
Чтобы использовать это, включите rounding.js в свой проект и вызовите функцию:
roundPathCorners(pathString, radius, useFractionalRadius)
Код и несколько тестовых путей находятся здесь: http://embed.plnkr.co/kGnGGyoOCKil02k04snu/preview
Вот как выглядят примеры из рендера Plnkr:
![SVG Path Rounding Examples]()
Ответ 2
Отправной точкой может быть использование-svg-curve-to-imitate-rounded-corner. Принцип состоит в том, чтобы преобразовать каждый угол с сокращенной относительной кубической (ыми). Этот пример очень простой и работает только с двумя возможными угловыми случаями.
Я думаю, что расширение этой подобной угловой замены сокращенной относительной кубической можно расширить, чтобы покрыть и другие сегменты пути. Каждый сегмент имеет координатную точку на кривой, которая должна быть заменена сегментом s
. Математика может быть интересной частью этого решения.
Ответ 3
Несмотря на то, что этот вопрос существует некоторое время, некоторые могут остановиться и попробовать это решение:
var BORDER_RADIUS = 20;
function roundedPath( /* x1, y1, x2, y2, ..., xN, yN */ ){
context.beginPath();
if (!arguments.length) return;
//compute the middle of the first line as start-stop-point:
var deltaY = (arguments[3] - arguments[1]);
var deltaX = (arguments[2] - arguments[0]);
var xPerY = deltaY / deltaX;
var startX = arguments[0] + deltaX / 2;
var startY = arguments[1] + xPerY * deltaX / 2;
//walk around using arcTo:
context.moveTo(startX, startY);
var x1, y1, x2, y2;
x2 = arguments[2];
y2 = arguments[3];
for (var i = 4; i < arguments.length; i += 2) {
x1 = x2;
y1 = y2;
x2 = arguments[i];
y2 = arguments[i + 1];
context.arcTo(x1, y1, x2, y2, BORDER_RADIUS);
}
//finally, close the path:
context.arcTo(x2, y2, arguments[0], arguments[1], BORDER_RADIUS);
context.arcTo(arguments[0], arguments[1], startX, startY, BORDER_RADIUS);
context.closePath();
}
Трюк состоит в том, чтобы начать (и остановиться) в середине первой строки, а затем использовать функцию arcTo
, которая описана очень красиво здесь.
Теперь вам просто нужно найти способ выразить все ваши фигуры как полигоны.