Проблема с анимацией fontSize в react-native-reanimated: подёргивание текста
Исходный код для воспроизведения: https://snack.expo.dev/uw3en-9CwCiCIQ1PX-GOl
Описание проблемы:
При изменении fontSize с помощью react-native-reanimated (ранее использовался стандартный пакет анимации react-native) наблюдается заметное подёргивание текста - перескок с пикселя на пиксель. Это проявляется как при изменении масштаба (scale), так и при прямой смене fontSize. При масштабировании эффект менее заметен, но всё равно ощущается. Ускорение анимации устраняет проблему, однако требуется сохранить текущую скорость.
Результаты тестов на разных частотах обновления:
- 60 Гц (Android): подёргивание хорошо заметно.
- 120 Гц (Android): подёргивание практически не заметно или слабо выражено (данные получены от другого пользователя).
- 144 Гц (ПК): эффект смазывания (мыло), другой пользователь не заметил.
Рекомендация и текущая реализация:
Было предложено использовать линейную интерполяцию, но эффект не достигнут. Используется шаг 0.1. Документация: https://docs.swmansion.com/react-native-reanimated...
Пример анимированного стиля (код):
const animatedStyle = useAnimatedStyle(() => ({
fontSize: interpolate(fontSize.value, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13])
}));Пояснение: значение изменяется от 1 до 20, на выходе получается fontSize от 11.1 до 13 с шагом 0.1. Отсутствие плавности связано с тем, что рендеринг текста привязан к целым пикселям, и дробные значения fontSize округляются по-разному на разных устройствах. Рекомендуется использовать scale для анимации вместо fontSize, либо увеличить количество опорных точек интерполяции для более мелкого шага (например, шаг 0.01). Также можно рассмотреть применение useDerivedValue для сглаживания изменений.