#konvajs
#конвайс
Вопрос:
Добрый день, читатель.
Я использую Konva.textPath для создания изогнутого текста. Я вычисляю путь на основе длины текста и угла, под которым он должен быть изогнут (например, от 270 до 90 наполовину изогнут, 359 от 0, это почти сам круг). Когда я передаю path в Konva.Path, он отлично рисуется, но с помощью textPath (в некоторых случаях) он отображает без последних букв и с неправильными интервалами между буквами. Я видел эту проблему на github, но я не уверен, что это та же проблема.
Вы можете увидеть прикрепленные изображения, с их путями вы можете найти вычисления в codesandbox
Если требуется дополнительная информация, пожалуйста, спросите.
Спасибо.
Path 1
M6.587352859507078 6.779702002611884,
A665.1292665214339, 665.1292665214339, 0, 0, 0, 271.78815041484745 4.465329704342594
Path 2
M8.968283494812425 14.597383097232182,
A993.126844893427, 993.126844893427, 0, 0, 0, 268.2165426505044 12.334957814595896
Комментарии:
1. Ссылка на вашу изолированную среду не работает. Возможно ли, что шрифт, который вы хотите использовать, отсутствует при отображении текстового пути?
2. Извините, я обновлю его сейчас. Это шрифт по умолчанию, с пользовательскими шрифтами он намного заметнее
3. Ссылка теперь работает. Хммм, очень странно, похоже, что проблема хуже всего при «низком изгибе».
Ответ №1:
Это не ответ, но дает некоторое представление о потенциальном самостоятельном решении на случай, если оно вам понадобится.
В общем, алгоритм для текста в пути концептуально прост, но его реализация немного сложна. Konva предоставляет вам те же возможности, что и необработанные команды HTML5 canvas в отношении этой задачи, поэтому нет необходимости отказываться от Konva.
Концепция
- есть путь и строка;
- получить прямолинейное размещение символов в строке (учитывает пары кернингов, чтобы обеспечить приятный интервал) — легко достигается;
- найти позицию на пути, где должен начинаться и заканчиваться каждый символ — не так просто;
- нарисуйте текст.
Сложный шаг равен 3, потому что нет способа предсказать путь. Это «может» быть прямая линия, или круг, или эллипс, но вы должны предположить непредсказуемую безумную зубчатую петлю.
Я игнорирую любое выравнивание или дополнительное заполнение символов, чтобы упростить задачу.
Для каждого символа вы будете знать начальную точку (x, y) для рисования — это начало пути для первого символа и конечная точка предыдущего символа для каждого последующего символа в строке. Знание начальной точки — это хорошо, теперь вам нужно найти конечную точку символьного пространства.
Теперь требуется краткое обсуждение метода path.getPointAtLength(). Холст знает длину любого пути, который вы попросите его нарисовать, и вы можете задать ему точку (x, y) для любого расстояния вдоль этого пути (в исходном коде Konva есть код для этого — это интересное чтение!). Итак, учитывая путь длиной, скажем, 100, вы можете запросить точку (x, y) длиной 42 с помощью path.getPointAtLength(42), и Konva вам сообщит.
Ну и что? Мы можем использовать это, чтобы найти конечную точку символа на кривой.
Вам понадобится алгоритм, который делает это:
- сделайте первоначальное предположение о длине — что-то вроде длины в начале символа эта ширина символа является разумной.
- Попросите указать точку в этой позиции на пути.
- Вычислите длину прямой линии от точки до точки между началом символа и этой точкой.
- Если путь изогнут / изогнут, то эта длина будет < ширина символа, и вам нужно повторить попытку с большим расстоянием, если вы промахнетесь, тогда идите немного короче.
- Повторите шаги 2-4, каждый раз регулируя длину с шагом.
То, что вам нужно, — это бинарный подход, чтобы ваши шаги сокращались каждый раз, тем самым достигая совершенства в какой-то момент. Хотя вы должны определить допуск, чтобы отказаться, когда найдена достаточно близкая точка.
Помните, что то, что вы здесь делаете, — это нащупывание точки на пути, где конечная точка символа, который вы хотите нарисовать, будет выглядеть разумно.
После того, как у вас есть позиции символов, вы делаете немного больше математики, чтобы определить угол поворота и положение каждого символа в левом верхнем углу. Затем вы можете вывести текст.
Если вам нужно выравнивание или интервал между символами, вы можете легко добавить эти функции, как только у вас будет запущен основной алгоритм.
В моем блоге есть похожее сообщение в блоге.
Получайте удовольствие.
Комментарии:
1. Спасибо за ваш ответ, я углублюсь в него!
Ответ №2:
Похоже, логика рендеринга Konva.TextPath
просто не идеальна, поэтому она имеет несогласованные интервалы между буквами.
О пропущенной последней букве. Вы вычисляете ширину текста как
const textLength =
textNode.getTextWidth()
(textNode.text().length - 1) * textNode.letterSpacing();
Это правильное решение для прямого Konva.Text
, но Konva.Path
использует приближения при рендеринге по указанному пути. Поэтому результирующий текст может занимать большую длину. Поэтому для последней буквы нет места. В качестве обходного пути вы можете немного увеличить textLength
. Например, путем добавления textNode.fontSize()
.
Комментарии:
1. Спасибо за ваш ответ. Я попробовал это решение, также я попытался добавить случайные числа, например, 10% длины, но все еще сталкивался с некоторыми плохими случаями. одним из таких случаев является то, что текст нельзя обвести. В качестве обходного пути для букв я проверяю исходный текст и длины глифов, если они разные, я меняю диапазон на 1, поэтому он не будет отображать текст без букв. Я знаю, что это тоже не очень хорошее решение, есть ли какой-либо другой способ повлиять на вычисления?