I was recently tasked with building a frontend camera component that allows users to upload images of their identification cards to a backend service. In this post I'll demonstrate how I created the component by explaining how to configure a live media stream and capture a snapshot with React hooks, and how to style and position the elements using Styled Components. As such, the article assumes a working knowledge of functional components in React 16.x and the Styled Components library. Below you can see a demo of the component in action, and feel free to play around with the complete solution on my Code Sandbox as you read along. Enjoy!
Configuration
Letβs begin by accessing the browser navigator and invoking the
Loading...
The
With the stream stored in local state it can then be bound to a
Loading...
Loading...
Positioning
With the media stream configured we can start to position the video within the component. To enhance the user experience, the camera feed should resemble an identification card. This requires the preview container to maintain a landscape ratio regardless of the native resolution of the camera (desktop cameras typically have a square or landscape ratio, where we assume that mobile devices will capture the images in portrait). This is achieved by calculating a ratio that is >= 1 by always dividing by the largest dimension. Once the video is available for playback (i.e. when the
In order for the component to be responsive, it will need to be notified whenever the width of the parent container has changed so that the height can be recalculated.
Similar to before, the ratio calculation is abstracted into a custom hook and returns both the calculated ratio and setter function. Since the ratio will remain constant we can utilise React's
Loading...
Loading...
The current solution works well if the video element is smaller than the parent container, but in the event that the native resolution is larger it will overflow and cause layout issues. Adding
Loading...
We only want to apply the offsets in the event that the video (v) is larger than the parent container (c). We can create another custom hook that uses an effect to evaluate whether an offset is required and returns the updated results whenever any of the values change. At this point we now have a responsive live feed that roughly resembles an identification card and is correctly positioned within the parent container.
Enjoying the article?
Support the contentLoading...
Loading...
Capture / Clear
To emulate a camera snapshot, a
Loading...
The arguments supplied to the
Loading...
To discard the image, the canvas is reverted to it's initial state via a
Loading...
Loading...
Styling
With the ability to capture an image, all that remains is to implement a card-aid overlay, a flash animation on capture, and style the elements using Styled Components. The overlay component is a white rounded border layered on top of the video to encourage the user to fit their identification card within the boundary, with an outer box-shadowed area acting as a safe-zone to prevent clipping. The flash component has a solid white background and is also layered on top of the video, but will initially appear hidden due to a default opacity of 0. The keyframes animation triggers whenever the user captures an image, which briefly sets the opacity to 0.75 before quickly reducing it back to zero to emulate a flash effect. Adding a local state variable,
Loading...
Loading...
Conclusion
For the moment the component serves to provide images as proof of authenticity, and is used alongside a form where users manually input field information from the identification cards. I'm hoping to follow this post up with an integration with OCR technology to scrape the fields from the images and remove the requirement for the form altogether. Thanks for reading along, and special thanks to Pete Correia for taking the time to review the component code.