Аннотация
В этой статье я расскажу о своем опыте работы с приложением для рисования. Объясняя, что я видел и что получилось в результате, я приведу полный пример того, как производительное приложение для рисования React Native может быть реализовано с использованием библиотеки React Native Skia.
Введение
Реализация этой картины была задачей на моей предыдущей работе, и во время разработки я столкнулся со многими библиотеками и решениями, но ни одно из них не было именно тем, что я хотел. Я также искал и нашел много примеров, но ни в одном из них не использовалось изображение по умолчанию (каркас) над покрасочной штангой. По следующим диаграммам вам будет легче лучше понять:
Какие были остальные:
В чем заключалась моя задача:
Как вы можете видеть на второй диаграмме, карандаш находится на каркасном изображении, а эффекты карандаша (линии) должны быть под каркасом, и это была сложная часть этой задачи.
TL; DR; Если вам нравится вставлять код, вот оно.
Основное решение
Без какой-либо бесполезной дополнительной информации и объяснений, основным решением для таких требований является использованиеreact-native-skia
. Я нашел несколько примеров рисования или реализаций React Native, но все они были очень плохо производительными и определенно не были надежными для производства. Эта статья очень полезна для понимания SVG в React Native и того, как он работает, и как разработчик может работать со свойствами SVG наряду с использованием обработчиков жестов.
Работа со Skia
Я прочитал много статей и примеров и заметил, что единственным решением будет использование react-native-skia
. Наряду с этим я нашел статью, которая могла бы стать очень полезным образцом react-native-skia
. Но тем не менее, мое основное требование осталось. Мне понадобился каркас в малярной штанге, но все образцы были реализованы пустой белой штангой.
Разговаривая с Уильямом Кандиллоном
В процессе разработки, читая исходные коды react-native-skia
, я нашел несколько решений для решения моей основной проблемы, но в некоторых случаях они не работали так, как я хотел, поэтому мне пришлось поговорить с участниками react-native-skia
о некоторых изменениях или задать некоторые вопросы, и я открыл вопрос и PR. К счастью, Undet, пиарщик, William Candillon, создатель react-native-skia
, поговорил со мной и его гидом, я понял, хотя он не мог мне помочь ☹️. Я только что глубоко погрузился в исходный код, чтобы найти свое решение.
Что такое react-native-skia
Если вы посмотрите на skia.org, вы поймете, что это библиотека 2D-графики, которая служит графическим движком для Google Chrome и ChromeOS, Android и Flutter, и он был написан на C/C++ и William с использованием NDK, используемого внутри Android и iOS, и с использованием модулей React Native, которые использовали его функциональные возможности в среде React Native.
В конце концов
Да, после долгих исследований, чтения исходного кода и общения с участниками я обнаружил, что могу использовать Canvas
компонентов, Canvas
из react-native-skia
не для SVG. А также компонент Path
для карандаша и линий. Итак, мои результаты стали следующими кодами:
<Canvas ref={drawRef} style={styles.paintBoom} onTouch={touchHandler}> <Group> <Fill color={palette.white} /> {lines?.map((line, index) => ( <Path key={`line_${line.path.toSVGString()}_${index}`} style="stroke" strokeJoin="round" strokeCap="round" path={line.path} paint={line.paint} strokeWidth={line.paint.getStrokeWidth()} color={line.paint.getColor()} /> ))} <PaintingBodyPen path={path} /> {!!image && ( <Image x={0} y={0} image={image} width={drawWidth} height={drawHeight} fit="contain" /> )} </Group> </Canvas>
Как видите, Canvas
со свойством onTouch
может выполнять функции карандаша, а его эффекты будут нарисованы paintingBodyPen
компонентом.Fill
компонент играет роль фона, а рендеринг цикла — это часть lines. Наконец, компонент Image
— это каркас, о котором я беспокоился.
Объяснение реквизита
Я должен объяснить некоторые реквизиты, чтобы прояснить их использование:
- ref: этот объект ref взят из верхнего уровня контекста, и я перешел к использованию некоторых
Canvas
функций, таких как экспорт нарисованных вещей в виде изображения. - onTouch: это функция-обработчик, которая ожидает результат useTouchHandler и состоит из трех шагов: запуск, активация и завершение. Если вы посмотрите на коды, их легко понять.
- onStart: в кодах начальных шагов попробуйте получить цвет и strokeWidth из хранилища и установить их в path и paint, что они были созданы с помощью useValue:
const path = useValue(Skia.Path.Make()); const paint = useValue(Skia.Paint());
- onActive: игнорировать условие
shouldPaint
, оно пытается предотвратить рисование при открытии цветовой палитры или меню обводки. Внутри onActive он пытается вычислить текущую позицию карандаша и зарегистрировать ее внутри объекта path. - onEnd: на этом уровне пришло время добавить нарисованную линию в хранилище и историю, сбросить то, что нарисовал пользователь, и подготовить путь и нарисованное объект для обработки следующего касания. После обновления магазина новая линия будет добавлена в стрелу, и пользователь не почувствует преобразования линии карандаша в один из элементов нарисованных линий.
Магазин и остальные инструменты
Я использовал управление магазином Zustand, потому что оно может работать из дерева ReactJs, и эта функция сделала мою реализацию такой производительной. Другие вещи, такие как получение разрешения и сохранение нарисованного изображения в виде файла JPG в галерее, не являются моей темой, поэтому, если вам интересно, вы можете посмотреть код.
Результат
Нет необходимости объяснять больше. Смотреть это:
Благодарности
Спасибо всем, кто помог мне с этим модулем и статьей. Примечательно, что мой дорогой друг Саид Падьяб провел пару часов, просматривая эту статью, чтобы сделать ее более простой, качественной и разборчивой.