camera-preview
camera-preview copied to clipboard
start()'s width, height, x and y show very inconsistent behavior across browsers
Describe the bug
CameraPreview.start({ /* params */ }) takes he paramters width, height, x and y to position the preview image.
I usually get those values from the parent element's bounding client rect with the getBoundingClientRect() function, which gives me width, height, left and top with float precision.
Using those values directly in start() works well in Chromium 119 on Desktop.
In Android WebView, width, height and y only work if I Math.floor() them to integers (while x happily accepts floats!?!).
In Firefox 120 on Desktop they work with floats except for height, which doesn't seem to work at all, no matter what type or number I use (but I didn't spend very much time debugging the issue in FF).
This makes working with this pluging very unpleasant.
To Reproduce
Try it in different browsers and WebView.
Expected behavior
- Consistent behavior of
width,height,xandyacross browsers - All of them should have the expected effect
- They all work with floats for correct scaling
Screenshots If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: Ubuntu 22.04
- Browser Chromium 119, Firefox 120
Smartphone (please complete the following information):
- Device: Android Emulator, API 33 | physical Pixel 7 phone
- OS: Android
- Browser: Android WebView 103 | Android WebView 120
Additional context
If the preview can only scale to the next integer, it is really hard to integrate it into the layout that scales to several decimal places float precision. It becomes even harder as the preview is on top of all html elements and can't be covered by a mask. This is another thing that is only an issue in the WebView, while on desktop the preview perfectly attaches to it's parent component and can be layered with it as excepted.
I came up with a workaround, where I hide the parent element that I have defined in CameraPreview.start() behind the app, then use CameraPreview.captureSample() to capture samples from the preview stream, convert those samples to dataURL's (via a canvas element) and then use those dataURL's as src for an img component that is visible in the DOM. This img component can be scaled and placed without any issues.
This solution is not very performant but good enough for what I'm trying to achieve.
I wonder what CameraPreview is doing to the parent element to make it so stubborn.
EDIT: doing the conversion like this instead of using a canvas wil improve the performance significantly.