Разработка
Анимация текста вдоль траектории в Jetpack Compose
Это можно использовать для создания причудливой графики или анимации строки текста.
В этой статье мы научимся рисовать текст по траектории (path) внутри холста Compose. Это можно использовать для создания причудливой графики или анимации строки текста.
Настройка текста
Давайте начнем с определения текста:
val text = remember { "Text on a Path" } val style = remember { TextStyle( color = Lime400, fontSize = 64.sp, fontWeight = FontWeight.Bold, ) }
В этом коде мы устанавливаем текст, который хотим разместить по контуру, а также создаем TextStyle
. Этот стиль нам нужен в нескольких местах, поэтому лучше определить его как значение для дальнейшего использования.
Далее нам нужно измерить наш текст:
val textMeasurer = rememberTextMeasurer() val result = textMeasurer.measure(text = text, style = style)
После создания TextMeasurer
мы можем измерить наш текст, передав и текст, и стиль. Это вернет TextLayoutResult
, который вычисляется путем применения выбранного шрифта к тексту.
Этот результат на самом деле содержит гораздо больше деталей, чем нам нужно. Сейчас мы просто хотим знать положение и размер каждого символа.
Рисуем текст
Определив и измерив текст, мы теперь можем создать траекторию (путь) и рисовать вдоль него.
val path = Path() // Define our path here, before measuring it val measure = PathMeasure() measure.setPath(path, false)
Сначала нам нужно создать Path
и определить, как он выглядит, используя предоставленные функции. После определения нам нужно измерить путь с помощью PathMeasure
. Это даст нам дополнительную информацию о пути, например, его длину или положение любой точки на нем.
Теперь мы можем перебрать каждый символ в тексте и нарисовать его:
val textWidth = result.getBoundingBox(text.lastIndex).bottomRight.x text.forEachIndexed { index, char -> val rect = result.getBoundingBox(index) val distance = rect.left + ((measure.length - textWidth) * progress) val pathOffset = measure.getPosition(distance) drawText( textMeasurer = textMeasurer, text = char.toString(), style = style, topLeft = pathOffset - Offset(0f, rect.height * .5f), size = Size(rect.width, rect.height) ) }
Сначала мы получаем ширину всего текста, проверяя положение x нижнего правого угла последнего символа.
Затем мы проходим по каждому символу и вычисляем, как далеко на пути он должен быть нарисован.
Функция getBoundingBox()
даст нам границы одного символа. Крайнюю левую точку этих границ можно добавить к доступному расстоянию на пути, которое равно общей длине пути за вычетом ширины текста (Примечание: убедитесь, что длина вашего пути больше длины вашего текста).
Затем, чтобы анимировать вдоль пути, мы просто умножаем это доступное расстояние на анимированное значение с плавающей точкой (0f..1f
).
С помощью distance
мы можем получить смещение нашего символа вдоль пути с помощью measure.getPosition
.
При рисовании текста мы передаем этот pathOffset
за вычетом половины высоты символа, чтобы он был отцентрирован на пути.
Помимо смещения, мы также передаем textMeasurer
, сам символ, наш определенный TextStyle
и размер измеренных границ символа.
Если мы запустим это, то получим такой результат:
Все символы размещены правильно, но нам также нужно повернуть их в соответствии с направлением пути. К счастью, PathMeasure
также может дать нам касательную любой точки вдоль пути.
text.forEachIndexed { index, char -> ... val rotation = measure.getTangent(distance).let { tan -> (atan2(tan.y, tan.x) * (180 / PI)).toFloat() } rotate( degrees = rotation, pivot = pathOffset, ) { drawText( ... ) } }
Используя касательную, мы можем вычислить поворот в градусах, используя некоторую базовую тригонометрию.
Используя rotation
, мы можем обернуть наш drawText
блоком поворота и передать вычисленные нами градусы. Мы также передаем pathOffset
в качестве опорной точки, так что буква вращается вокруг своей центральной точки.
И теперь наш текст анимируется по пути, с правильным позиционированием и ориентацией.
Спасибо за чтение и удачи!
-
Видео и подкасты для разработчиков3 недели назад
Пагинация: от идеи до реализации
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.25
-
Видео и подкасты для разработчиков3 недели назад
История, принципы и концепции библиотеки навигации Decompose
-
Исследования3 недели назад
Bidease: мобильный маркетинг 2025 — баланс AI, удержания и конфиденциальности