Connect with us

Разработка

Анимация текста вдоль траектории в 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 в качестве опорной точки, так что буква вращается вокруг своей центральной точки.

И теперь наш текст анимируется по пути, с правильным позиционированием и ориентацией.

Спасибо за чтение и удачи!

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: