Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Body append #129

Open
VincentGillot opened this issue Sep 28, 2021 · 5 comments
Open

Body append #129

VincentGillot opened this issue Sep 28, 2021 · 5 comments

Comments

@VincentGillot
Copy link

I was wondering why is the video re-appended to the body? I'm using this inside a React app and it's being put outside of the screen. It would be nice for it to just simply use the current video tag or choose a parent element to be used for appending. And i can't style it because all the styles are being overwritten by the instance construction.

@danimoh
Copy link
Member

danimoh commented Feb 4, 2022

Hello, the video is not being re-appended to the body, it is only being appended to the body, if it is not appended to the DOM yet at the time the QrScanner instance is created.
This is to avoid issues with iOS which disallows playing a video that's not in the DOM or hidden, see

// Avoid Safari stopping the video stream on a hidden video.
// See https://github.com/cozmo/jsQR/issues/185
let shouldHideVideo = false;
if (video.hidden) {
video.hidden = false;
shouldHideVideo = true;
}
if (!document.body.contains(video)) {
document.body.appendChild(video);
shouldHideVideo = true;
}

requestAnimationFrame(() => {
// Checking in requestAnimationFrame which should avoid a potential additional re-flow for getComputedStyle.
const videoStyle = window.getComputedStyle(video);
if (videoStyle.display === 'none') {
video.style.setProperty('display', 'block', 'important');
shouldHideVideo = true;
}
if (videoStyle.visibility !== 'visible') {
video.style.setProperty('visibility', 'visible', 'important');
shouldHideVideo = true;
}
if (shouldHideVideo) {
// Hide the video in a way that doesn't cause Safari to stop the playback.
console.warn('QrScanner has overwritten the video hiding style to avoid Safari stopping the playback.');
video.style.opacity = '0';
video.style.width = '0';
video.style.height = '0';
if (this.$overlay && this.$overlay.parentElement) {
this.$overlay.parentElement.removeChild(this.$overlay);
}
// @ts-ignore
delete this.$overlay!;
// @ts-ignore
delete this.$codeOutlineHighlight!;
}
if (this.$overlay) {
this._updateOverlay();
}
});

You can avoid this by creating the QrScanner instance only as soon as the video element has been added to the DOM.
If you're using a UI framework, note that most frameworks offer something like a mounted hook, that tells you that a component's DOM elements have actually been added to the DOM.

Instead of doing the checks linked above in the constructor, I could also do them on each play().
Do you think that would help?

@brettwillis
Copy link

brettwillis commented Jun 8, 2022

@danimoh this line prevents us from showing the video inside the shadow DOM. Can't use it in UI frameworks that utilise shadow DOM (web components) e.g. LitElement.

if (!document.body.contains(video)) {

Edit: this particular problem is already raised by #168.

@webermax
Copy link

For our project, that's a show stopper, too.

@exetico
Copy link

exetico commented Jul 6, 2023

What's the progress on this? It's a show-stopper here, too (Lit are in use, indeed).

Have you done any work behind the scenes, @nimiq ? Thank you for a great solution for qr-scanner.

@exetico
Copy link

exetico commented Jul 6, 2023

@webermax Now we just need @nimiq to approve #241. You're welcome to use my fork, while we wait.

https://github.com/exetico/qr-scanner/tree/master

I'll remove my work, once the merge has (hopefully) been approved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants