ericblade / quagga2

An advanced barcode-scanner written in Javascript and TypeScript - Continuation from https://github.com/serratus/quaggajs
MIT License
765 stars 85 forks source link

Responsiveness #532

Closed Hugos68 closed 4 months ago

Hugos68 commented 10 months ago

When I start Quaqqa the container it is inside is immediately overflown and the preview takes up way more space than the container's space allows for, are there any examples of using it in a responsive manner?

github-actions[bot] commented 10 months ago

Thank you for filing an issue! Please be patient. :-)

ericblade commented 10 months ago

Hi there! Thanks for the question.

My findings so far have been that that is extremely hardware and software dependent, and that between desktop and mobile, or between Chrome, Firefox, and WebKit, and sometimes between different versions of the same, you'll find different behavior for all of them.

Unfortunately, I didn't actually sit down and document anything on that, I just modified code and CSS and HTML until I found something that worked reasonably well for my specific use case.

You might try specifying a constraint for the camera to limit it's resolution, however, the browser or device can completely ignore that request if it wants.

If you decide to mess around with figuring out any specifics on how browsers handle that, please let me know, but here's what I'm presently using, and it seems to work quite well for my purposes

code, asking for a resolution between 480 and 1080

            Quagga.init({
                inputStream: {
                    type: 'LiveStream',
                    willReadFrequently: true,
                    constraints: {
                        width: {
                            ideal: 1920,
                            min: 640,
                        },
                        height: {
                            ideal: 1080,
                            min: 480,
                        },
                        ...(cameraId && { deviceId: cameraId }),
                        ...(!cameraId && { facingMode: { ideal: 'environment' } }),
                    },
                    target: scannerRef.current,
                },
                locator: {
                    patchSize: 'medium',
                    halfSample: true,
                    willReadFrequently: true,
                },
                numOfWorkers: 0,
                decoder: {
                    // readers: ['qr-code-reader'],
                    readers: ['upc_reader', 'ean_reader'],
                },
                locate: true,
            }, async err => {
                if (!err) {
                    Quagga.onProcessed(QuaggaOnProcessed);
                    Quagga.onDetected(errorCheck);
                }

                if (err) {
                    console.log('Error starting Quagga:', err);
                } else if (scannerRef.current) {
                    await Quagga.start();
                    if (killed) {
                        console.warn('**** Quagga killed before init complete');
                        Quagga.stop();
                    }
                }
            });

partial snippet of react component that attempts to constrain the video and canvas elements to the display dimensions, and account for orientation

    const isLandscape = deviceOrientation.alpha === 90 || deviceOrientation.alpha === 270;
    const actualWidth = isLandscape ? 480 : window.innerWidth;
    const actualHeight = isLandscape ? window.innerWidth : 480;

    return (
        <div className={css.scannerContainer} ref={scannerRef}>
            <video style={{ width: actualWidth, height: actualHeight }} />
            <canvas className="drawingBuffer" width={actualWidth} height={actualHeight} />
            {
                scannerOpen && (
                    <Scanner
                        cameraId={cameraId}
                        scannerRef={scannerRef}
                        onScannerReady={onScannerReady}
                        onDetected={onDetected}
                    />
                )
            }
Hugos68 commented 10 months ago

Thanks for the detailed answer! Your example definitely helps, would you say the original Quaqqa docs still apply in terms of attaching it to the DOM then?

ericblade commented 10 months ago

I think so? Is there a particular part of the docs you're wondering about?

Any information that you discover and find helpful, please feel free to share. Once I got a layout that worked for my application, I pretty much stopped messing around with layout. I'll probably be adding Q to a new application in the near future, though, so it's something I'll be messing with again hopefully soon if I can find the time :D

ericblade commented 10 months ago

I've been having a look at a React user library called Mantine, and it has a component called AspectRatio that looks like it tries to force video elements to behave wrt size, also . So I think there's almost definitely some browser weirdness with certain browsers that want to make the video take up all the space it possibly can, even if it causes the element to go way out of it's bounds... which imo, the browser should also prevent... but... here we are. :D

ericblade commented 4 months ago

I was thinking about this issue a bit over some other development I was doing, and I noted that the HTML meta tags that we use to flag a web app as being suitable for use on mobile devices, such as the viewport tags for width=device-width .. those cause changes to how mobile browsers render the content, but not to desktop. I think that is probably at fault here for some things being really weird between mobile and desktop.