Criando mascara sobre a câmera no React Native usando SVG
Criando máscara sobre a câmera no React Native usando SVG de forma responsiva
Fala galera! Neste post irei abordar um assunto que demorei um tempo para conseguir solucionar, também não encontrei muito conteúdo na internet a respeito: aplicar uma máscara em cima da câmera no React Native.
Novamente vou me basear em um design encontrado no Dribbble, onde a câmera é sobreposta por uma camada com instruções, próximo ao resultado que queremos atingir.
Pré requisitos e conhecimentos prévios desejáveis:
Estou considerando neste post que você já sabe sobre layout e, também, como criar um projeto em React-Native, dito isto, será ignorada toda a parte de criação e configuração do projeto.
- React Native
- Layout com FlexBox
- react-native-cli
- conhecimentos básicos de SVG
Falei demais, vamos ao que importa!
Adicionando e configurando as bibliotecas
Primeiramente vamos instalar a biblioteca react-native-camera
e a biblioteca react-native-svg
, após isso vamos linkar as dependências nativas ao nosso projeto, podemos fazer isso com os comandos abaixo:
yarn add react-native-camera react-native-svgreact-native link
caso esteja utilizando Windows, o react-native-camera possui alguns passos a mais para ser instalado, recomendo que olhe este link a partir da documentação oficial: https://github.com/react-native-community/react-native-camera/blob/master/docs/installation.md#windows
Após linkar as dependências, mais alguns passos são necessários para a biblioteca react-native-camera
:
Adicionar a linha abaixo ao seu arquivo app/build.gradle
;
android {
...
defaultConfig {
...
// insira esta linha
missingDimensionStrategy 'react-native-camera', 'general'
}
}
Adicionar as permissões de acordo com a plataforma para a qual você está implementando:
Para o Android vamos adicionar as permissões ao arquivo Manifest
;
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Para iOS vamos adicionar as permissões ao arquivo Info.plist
.
<key>NSCameraUsageDescription</key>
<string>Sua mensagem ao usuário quando a câmera é acessada pela primeira vez</string>
<key>NSMicrophoneUsageDescription</key>
<string>Sua mensagem ao usuário quando o microfone é acessado pela primeira vez</string>
Após instalar e linkar as dependências, vamos importar o componente RNCamera
de nossa biblioteca.
import { RNCamera } from ‘react-native-camera’;
Feito isso, vamos inicializar nosso componente RNCamera
com as seguintes props: style
que será a estilização do nosso componente, ref
a qual vamos utilizar para definir uma referência ao nosso componente, (útil para quando formos tirar uma foto ou usar algum outro recurso da câmera) e type
para definir qual câmera vamos utilizar, frontal ou traseira. Para o type
podemos utilizar a constante incluída na biblioteca neste caso vamos utilizar a câmera frontal, então ficará assim.
Depois de inicializar a câmera, podemos começar a criar nosso componente da máscara, vamos utilizar a biblioteca react-native-svg
para isso.
Criando o componente de máscara (overlay)
Para que nosso componente ocupe toda a tela, vamos criar uma View
que terá a prop aspectRatio.
Esta prop é responsável por controlar o tamanho da dimensão de um componente quando este tamanho não for definido, neste caso, não definimos nenhuma dimensão, nem para width
, nem para height
, logo, a prop aspectRatio
irá preencher esses dois valores, basicamente seria a mesma coisa que:
<View style={{
width: Dimensions.get(‘window’).width,
height: Dimensions.get(‘window’).height
}}>
Dentro desta View
vamos criar um Svg
que ocupará todo a altura da tela, a largura será preenchida automaticamente, assim, não precisaremos definir a largura, para a prop viewBox
vamos calcular a partir do tamanho da tela do dispositivo, utilizando a Dimensions API do React Native.
const { height, width } = Dimensions.get(‘window’);const viewBox = `0 0 ${width} ${height}`
Dentro da tag Svg
vamos definir nossa máscara utilizando os componentes Defs
. Dentro de Defs
vamos definir Mask
, que terá dois componentes filhos: Rect
e Circle
. Para o Rect
vamos calcular as props height
e width
a partir da Dimensions API, e vamos definir a prop fill
para a cor #ffffff
.
No SVG quando aplicamos a prop fill a um elemento basicamente estamos dizendo o que será visível, um elemento com fill
#ffffff
por exemplo será totalmente visível, enquanto um elemento com fill#000000
não será.Por padrão a prop fill é
#000000
, para o componenteCircle
não será necessário declarar esta prop, já que queremos que o círculo seja transparente para podermos ver a câmera por trás, se fosse necessário usaríamos#000000
como valor da prop fill, mas este já é o valor padrão.
Ainda para o Circle
vamos declarar as props cx
e cy
que representam as coordenadas do centro do círculo e a prop r
que representa o seu raio, neste caso, queremos posicionar o círculo ao centro horizontal e um pouco acima do centro vertical, para fazer isso vamos calcular cx
como metade da largura da tela, e cy
como um terço dela usando os valores obtidos da Dimensions API, a outra prop a ser declarada é r
, que representa o raio do nosso círculo, o que também pode ser calculado a partir do tamanho da tela.
Como sabemos o raio é metade do diâmetro de um círculo, logo se dividirmos o valor largura da tela por 2, teremos um círculo com um diâmetro equivalente a largura do dispositivo, neste caso queremos um círculo com uma margem da borda, sendo assim, o diâmetro será um pouco menor que a largura do dispositivo, então vamos dividir a largura por 2.5.
Para finalizar nosso componente de máscara vamos definir mais um retângulo, mas dessa vez fora de Defs
, novamente vamos calcular altura e largura a partir da Dimensions API, iremos definir mais duas props fill
e mask
. Para o fill
podemos utilizar qualquer cor em hex
ou rgb(a)
, no caso de mask
vamos referenciar a máscara que definimos anteriormente, e este será o código final do nosso componente:
Agora, vamos utilizar nosso componente, como é um componente que ficará sobre a câmera, precisaremos aplicar position: absolute
em nosso componente RNCamera
e definir os valores das dimensões, já que o mesmo não é uma View
do React Native, logo, a prop aspectRatio
não irá funcionar tão bem neste cenário, os estilos para o componente de camera ficarão assim:
camera: { position: ‘absolute’, flex: 1, width: Dimensions.get(‘window’).width, height: Dimensions.get(‘window’).height},
Feito isso vamos instanciar o nosso componente CameraOverlay
, agora já devemos ter o resultado esperado.
Para adicionar mais alguns elementos sobre a máscara, instruções por exemplo, vamos criar uma outra View
com position absolute
, porém desta vez vamos definir o zIndex
para 2, para posicioná-la sobre a câmera e sobre a máscara, também precisaremos definir: top
, bottom
, left
e right
, para que esta View
ocupe toda a tela.
E este é o resultado final:
Este é o link do projeto no github caso queira modificar a partir dele: https://github.com/digital-heroes/camera-overlay-svg
É isso galera! foi um prazer enorme tomar um pouco do seu tempo. Espero que o post tenha ajudado bastante, se sim, por favor clique algumas vezes no botão de clap e compartilhe com alguém que conheça.
Obrigado pela leitura e até o próximo post!