Criando mascara sobre a câmera no React Native usando SVG

Wes Guirra
React Brasil
5 min readJun 24, 2019

--

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-camerae 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 componente Circle 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!

--

--

Wes Guirra
React Brasil

Desde que me entendo por gente, procuro maneiras de inovar para melhorar o mundo em que vivemos.