Closed mendozaarjay closed 1 year ago
I have the same issue. But I know that the camera is actually there. But I can't see it.
I can scan qr codes and see logs in xcode.
I'm guessing that the css is not enough for the rendered html.
In the guide, it says you have to add
--background: transparent into your css
and
document.querySelector('body').classList.add('scanner-active');
where you trigger scanner.
Doing this, gave me a camera as a background. But it kept all outher components on top of it. I'm guessing there is a lack of z-index. Since the code according to the guide is
<div style="position: absolute; left: 0px; top: -2px; height: 1px; overflow: hidden; visibility: hidden; width: 1px;">
<span
style="position: absolute; font-size: 300px; width: auto; height: auto; margin: 0px; padding: 0px; font-family: Roboto, Arial, sans-serif;"
>BESbswy</span
>
</div>
And what I can see, there is no z-index. Therefore everything is in the back for me.
Question to the dev team. Would it be possible to add a class/id/name or something that can be target with css? So I can play around and see if my own positioning would work?
I'm having the exact same experience. Did anyone figure out a solution for this? I noticed that if I swipe to go back/close my app (while in Android ) then I do see the camera open behind the app body (confirming that the camera is indeed opening).
This is by definition of the plugin. The plugin will just render a camera-view behind the DOM. Since capacitor can be used with whatever framework you want, if you want to use a framework at all, it is not possible to provide a general solution for this "issue".
You need to check your DOM elements, find the ones that are not transparent, and apply transparency to all the elements in front of the camera-view while scanning. Unfortunately there is no other solution for this without "killing" the possibility to create custom UIs.
@DannePeyya it would be possible to add css classes to the body once the scan starts, but this is currently not done since it is an easy task to do yourself. The view itself won't have a class at all, since it is rendered behind the complete DOM.
I make it working by adding this:
this.barcodeScanner.hideBackground(); document.body.style.opacity = '0'; document.body.style.background = 'transparent';
It works fine but I need to add a cancel button. That's something that everybody want.. No?
However, I'm not able to display any overlay... I just opened a ticket few minutes ago but I just read the comment from @thegnuu : "Unfortunately there is no other solution for this without "killing" the possibility to create custom UIs."
It is an absolutely pathetic spectacle!
Another question @thegnuu .
By definition, the plugin render the camera view behind and we need to make the application transparent.
Why not doing the opposite ? I mean bring the camera view ahead with a z-index that could be customized ?
@JoranLive
It is an absolutely pathetic spectacle!
First of all, nobody is forcing you to use this plugin, if you are not happy with it you are free to find another solution that works for you. All here are doing their best to provide a free plugin to the community, and comments like this will help absolutely nobody.
Why not doing the opposite ? I mean bring the camera view ahead with a z-index that could be customized ?
I guess you are not familiar with how capacitor works, otherwise you would know that there are some technical limitations on its usage. The camera view (native on ios and android) is completely encapsulated from the web content view which is used to display your App, this view is not freely movable within the DOM. It might be possible that there are some sort of fancy workarounds to open a camera stream natively in a different view, intercept it and forward this stream via some capacitor APIs to your DOM, but the technical overhead and complexity would be way to big, there are some security and performance concerns as well.
This is an issue that should not be that kind of a deal for a developer that works with capacitor and has basic knowledge how a DOM structure works, once you know how the plugin works.
I might be wrong and there is a simple way that I just cannot think about now, if so and you know about one, feel free to open a PR and share your knowledge with the rest of the community.
@thegnuu I'm sure I speak for the community in letting you know that the rest of us appreciate your work on this and the process of making it work was quite easy once the "issue" was fully understood!
Sorry about what I wrote, it was probably a bad day.
I appreciate this plugin and for sure you allowed me to save my time.
You are right, I'm absolutly not familiar with Capacitor for now.
However, I notice that I'm not the only one to face the issue with Ionic even if we followed the readme.
I will think about it and try to come back with suggestions.
Thank you
No worries, I understand that things can be frustrating sometimes :)
Unfortunately, as I said, I currently have no great idea how to simplify the setup since it is very individual...
Maybe adding some sort of demo or getting started with ionic and maybe pure js/html might be a good idea to begin with, what do you guys think? So that devs have some sort of starting point or working example to get started with... That would be easily done since I need some sort of dev environment anyways, I currently have an external repo for that.
Updating and simplifying the docs would be great as well I believe.
Mine it's just showing white screen weird
.scan-box { border: 2px solid #fff; box-shadow: 0 0 0 100vmax rgb(0, 0, 0, 0.5); content: ""; background: transparent; display: block; left: 50%; height: 300px; position: absolute; top: 50%; transform: translate(-50%, -50%); width: 300px; } .scan-button { background: transparent; margin: 0px; position: absolute; bottom: 100px; width: 100vw; height: 50px; z-index: 11; }
I don't understand why
Have you checked the complete DOM structure? There will be some element which still has a background set.
The only other reason might be that you don't have permission to access the camera, but this should be visible in the logs somewhere...
I had the same problem with my Ionic 6 app and solved it by adding 'opacity = 0' to the 'ion-content' of the page that calls 'startScan()' function, in addition to the steps and styling that mentioned in the docs. This worked for me and the camera view is now showing up. And this way I was able to add 'ion-header' that is shown above the camera view with a title and a close button that call 'stopScan()' and get all the styling back to normal. And the visibility of the 'ion-header' can be controlled by a parameter, for example 'isScannerOpen', that is toggled true or false according to the status of the BarcodeScanner
@JoranLive
Actually, your solution worked for me but without document.body.style.opacity = '0';
so only document.body.style.background = 'transparent';
is required to add in addition to await BarcodeScanner.hideBackground();
Maybe this can help some people. I messed with this issue on Android for a couple days. IOS worked fine based on instructions.
I had the same problem on iOS with Ionic v6 and just wanted to share the solution. Tag body
along with ion-content
have black/white background (dark/light mode) so the solution that worked for me was to set the class to body (such as .scanner-active
) and based on that to set variables to transparent:
.scanner-active {
--ion-background-color: transparent !important;
}
.scanner-active ion-content {
--background: transparent !important;
}
Here is a service for anyone needing a kickstart. With a mimic function on web so you can style your button and crosshair etc via ionic serve.
`import { Injectable } from '@angular/core'; import { BarcodeScanner, ScanResult } from '@capacitor-community/barcode-scanner'; import { Platform } from '@ionic/angular'; import { ToastServiceService } from './toast-service.service';
@Injectable({ providedIn: 'root' }) export class BarcodeScannerService { crosshairId = "QrCrosshair"; crosshairContainerId = "QrCrossHairContainer"; private crosshairContainer:HTMLElement; constructor( private toasts:ToastServiceService, private platform:Platform ) { this.createScannerElements(); }
async scan(){ try { let result:ScanResult // Check camera permission // This is just a simple example, check out the better checks in plugin repo
this.hideBackground();
if(this.platform.is('desktop')){
result = await this.mimicScan()
}else{
const checkResult = await BarcodeScanner.checkPermission({ force: true });
if(!checkResult.granted){
return;
}
result = await BarcodeScanner.startScan();
}
this.showBackground();
return {result}
}catch(err){
console.log(err);
await this.toasts.showToast('Scanner Failed','');
}
}
private async mimicScan(){ let res = await new Promise<{ hasContent:boolean, content:string }>((resolve) => { setTimeout(()=>{ let result={ hasContent:false, content:'Test' } resolve(result) },10000) }) return res }
private async hideBackground(){ if(!this.platform.is('desktop')){ await BarcodeScanner.hideBackground(); } document.body.style.opacity = '0'; document.body.style.background = 'transparent'; this.addCrosshair() }
private async showBackground(){ document.body.style.opacity = ''; document.body.style.background = ''; if(!this.platform.is('desktop')){ await BarcodeScanner.showBackground(); } this.rmCrosshair(); }
private createScannerElements(){ this.crosshairContainer = document.createElement("div");
// set the crosshairContainer style using CSS
this.crosshairContainer.style.position = "fixed";
this.crosshairContainer.id = this.crosshairContainerId;
this.crosshairContainer.style.top = "50%";
this.crosshairContainer.style.left = "50%";
this.crosshairContainer.style.transform = "translate(-50%, -50%)";
this.crosshairContainer.style.width = "100%";
this.crosshairContainer.style.height = "85%";
this.crosshairContainer.style.zIndex = "9999";
// create a new div element to contain the crosshair
let crosshair = document.createElement("div");
// set the crosshair style using CSS
crosshair.id = this.crosshairId;
crosshair.style.opacity = "";
crosshair.style.background = "";
crosshair.style.position = "fixed";
crosshair.style.top = "50%";
crosshair.style.left = "50%";
crosshair.style.transform = "translate(-50%, -50%)";
crosshair.style.width = "9em";
crosshair.style.height = "9em";
crosshair.style.border = "2px dashed #74a44c";
crosshair.style.borderRadius= "4px";
crosshair.style.zIndex = "9999";
// append the crosshair element to the container element
this.crosshairContainer.appendChild(crosshair);
// create a new button element for cancel
var cancelButton = document.createElement("button");
// set the cancel button style using CSS
cancelButton.textContent = "Cancel";
cancelButton.style.position = "absolute";
cancelButton.style.bottom = "0";
cancelButton.style.left = "50%";
cancelButton.style.transform = "translateX(-50%)";
cancelButton.style.padding = "10px";
cancelButton.style.borderRadius = "5px";
cancelButton.style.backgroundColor = "#aa240e";
cancelButton.style.color = "#f4f5f8";
cancelButton.style.width = "80%";
cancelButton.style.height = "50px";
// add an event listener to the cancel button to remove the container element when clicked
cancelButton.addEventListener("click", ()=>{
this.showBackground();
});
// append the cancel button to the container element
this.crosshairContainer.appendChild(cancelButton);
}
private addCrosshair(){ // append the crosshair element to the root element document.documentElement.appendChild(this.crosshairContainer); }
private rmCrosshair(){ document.getElementById(this.crosshairContainerId).remove(); } } `
Ionic 6: I have to do one more thing which is not mentioned in readme file. in body.scanner-active the readme here mentioned body.scanner-active { --background: transparent; --ion-background-color: transparent; }
But I had also to add
background: transparent;
so the result:
body.scanner-active { --background: transparent; background: transparent; --ion-background-color: transparent; }
Toggle body visibility worked for me Example
async startScan() { const body = document.getElementById('myBodyId'); try { body.style.visibility = 'hidden'; const result = await BarcodeScanner.startScan(); body.style.visibility = 'visible'; } catch (ex) { body.style.visibility = 'visible'; } }
I have this issue since upgrading to Ionic 7
I am using vue 3 with setup
configuration
This is my camera active class:
body.scanner-active
--background: transparent
--ion-background-color: transparent
and here is how I use the camera:
const startScan = async () => {
document.querySelector('body')?.classList.add('scanner-active')
// Check camera permission
// This is just a simple example, check out the better checks below
await BarcodeScanner.checkPermission({ force: true });
// make background of WebView transparent
// note: if you are using ionic this might not be enough, check below
BarcodeScanner.hideBackground();
barcodeStore.$patch({
scanInProgress: true
})
const result = await BarcodeScanner.startScan(); // start scanning and wait for a result
console.log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
console.log(result)
// if the result has content
if (result.hasContent) {
emit('setResult', result.content)
}
barcodeStore.$patch({
scanInProgress: false
})
};
Problems:
(here it should normally show up)
Logs of xcode:
To Native -> BarcodeScanner checkPermission 54809842
⚡️ TO JS {"granted":true}
⚡️ To Native -> BarcodeScanner hideBackground 54809843
⚡️ TO JS undefined
⚡️ To Native -> BarcodeScanner startScan 54809844
Thread Performance Checker: -[AVCaptureSession startRunning] should be called from background thread. Calling it on the main thread can lead to UI unresponsiveness
PID: 63437, TID: 4347239
Backtrace
=================================================================
3 CapacitorCommunityBarcodeScanner 0x0000000104eef154 $s32CapacitorCommunityBarcodeScanner0cD0C4scan33_E9781981B91FA2D5C67BE1318BC971C3LLyyFyyScMYccfU1_ + 512
4 CapacitorCommunityBarcodeScanner 0x0000000104eed9f4 $sIeg_IeyB_TR + 48
5 libdispatch.dylib 0x000000010527053c _dispatch_call_block_and_release + 32
6 libdispatch.dylib 0x0000000105271ff0 _dispatch_client_callout + 20
7 libdispatch.dylib 0x0000000105282800 _dispatch_main_queue_drain + 1196
8 libdispatch.dylib 0x0000000105282344 _dispatch_main_queue_callback_4CF + 44
9 CoreFoundation 0x00000001b1b016c8 42CCFC7B-FF32-3D25-8F01-CCB2AD843A8B + 632520
10 CoreFoundation 0x00000001b1ae302c 42CCFC7B-FF32-3D25-8F01-CCB2AD843A8B + 507948
11 CoreFoundation 0x00000001b1ae7eb0 CFRunLoopRunSpecific + 612
12 GraphicsServices 0x00000001ebcdd368 GSEventRunModal + 164
13 UIKitCore 0x00000001b3fdd668 CF21AD9C-EFBF-3961-A7C0-54BD30CEFEA9 + 3806824
14 UIKitCore 0x00000001b3fdd2cc UIApplicationMain + 340
15 App 0x0000000104a3bfbc main + 64
16 dyld 0x00000001d03e0960 4B042F28-0D14-30EC-A1DE-3DBB10866AD7 + 88416
The permission granting works
Also the camera seems to "start" somehow
But it does not get to the result
part at all (maybe because I am not able to take a picture)
All I see is a white screen.
Any ideas?
@donmb1 Your setup looks good in general, and the logs look okay as well.
You might just need to check your DOM tree, I am not sure on which level ionic injects the CSS variables, but it might be higher up in the DOM than the body, which means that your variables on the body won't work as you might expect and are overwritten by ionic. Unfortunately, they change this behavior from time to time...
The camera will never show up in the DOM if you are on iOS or Android, this is by design. The camera view is rendered behind the webview in native environments.
@thegnuu I see well its a bit confusing to me that it all of a sudden does not work anymore. Now I tried to migrate back to Ionic 6 but I have the same "white screen" problem there and it worked totally fine before. I am not sure what broke it tbh.
@donmb1 there were no changes in the behavior of this plugin in the last months, so I guess the problem is somehow related to your project. I would try to clean up everything (node_modules, cached files aso.) and then try again. I had some weird issues trying to migrate between ionic versions in the past as well, but they were usually not related to the plugins I used ;)
@thegnuu yeah I know this exercise very well :-D unfortunately it did not help yet I probably need to debug deeper
@donmb1 weird, unfortunately, I am not really able to help you and verify that it is not an issue with the plugin without a repo to reproduce your problem. If you can share your stuff I am happy to have a look, if you cannot share it it will be hard for me...
I am cleaning up "old" issues and will close this for now. If there are still problems feel free to open a new issue.
Just a little change in CSS and the problem will get resolved. I am using ionic 7
//Import Renderer2
import { Component, OnInit, Renderer2 } from '@angular/core';
//Call the function like this
async scan() {
this.renderer.addClass(document.body, 'scanner-active');
// Check camera permission
// This is just a simple example, check out the better checks below
await BarcodeScanner.checkPermission({ force: true });
// make background of WebView transparent
// note: if you are using ionic this might not be enough, check below
BarcodeScanner.hideBackground();
const result = await BarcodeScanner.startScan({ targetedFormats: [SupportedFormat.QR_CODE] }); // start scanning and wait for a result
// if the result has content
if (result.hasContent) {
console.log(result.content); // log the raw scanned content
this.renderer.removeClass(document.body, 'scanner-active');
}
}
// global.scss
body.scanner-active {
--background: transparent;
--ion-background-color: transparent;
opacity: 0; // Add this line is global.scss file
}
Hope this will solve the problem.
in same component add
< div id="container" >
< /div >
and in app.component.html
in ion-app
-> < ion-app class="scanner-hide" >
at the end add < div class="scanner-ui"> < /div >
and in global.scss
.scanner-ui { display: none; } .scanner-hide { visibility: visible; }
body.qrscanner { background-color: transparent; } body.qrscanner .scanner-ui { display: block; } body.qrscanner .scanner-hide { visibility: hidden; }
Holaa quiero compartir mi solución para el botón de regreso
//estilos en global.css
--background: transparent;
--ion-background-color: transparent;
opacity: 0; // Add this line is global.scss file
}
display: none;
}
display: flex;
z-index: 300;
position: absolute;
background-color: #272761;
max-height: 150px;
align-items: center;
color: #ffffff;
bottom: 0;
padding: 10px 20px;
width: 100%;
} .return img{ width: 40px; } .return p{ margin-left: 30px; } ////////////////////////////////////////////// index.html
Cancelar
//////////////////////////////////////////// componente de implementacion
ademas importe import { Component,Renderer2 } from '@angular/core';
en el constructor private renderer:Renderer2
async scanQR() {
this.renderer.addClass(document.body, 'scanner-active');
// Check camera permission
// This is just a simple example, check out the better checks below
await BarcodeScanner.checkPermission({ force: true });
// make background of WebView transparent
// note: if you are using ionic this might not be enough, check below
BarcodeScanner.hideBackground();
this.renderer.addClass(document.getElementById('CancelScanner'), 'return');
const result = await BarcodeScanner.startScan({ targetedFormats: [SupportedFormat.QR_CODE] }); // start scanning and wait for a result
// if the result has content
if (result.hasContent) {
console.log(result.content); // log the raw scanned content
this.renderer.removeClass(document.body, 'scanner-active');
this.tbCodigo=result.content
}console.log(result.content); // log the raw scanned content
}
posiblemente para el fondo lo mas sencillo sea crear un png con el centro transparente
CABE ACLARAR QUE CASI NO CONOZCO IONIC Y NO SE SI ESTA SOLUCION PUEDA AFECTAR EL RENDIMIENTO O ALGO MAS
Just a little change in CSS and the problem will get resolved. I am using ionic 7
//Import Renderer2 import { Component, OnInit, Renderer2 } from '@angular/core'; //Call the function like this async scan() { this.renderer.addClass(document.body, 'scanner-active'); // Check camera permission // This is just a simple example, check out the better checks below await BarcodeScanner.checkPermission({ force: true }); // make background of WebView transparent // note: if you are using ionic this might not be enough, check below BarcodeScanner.hideBackground(); const result = await BarcodeScanner.startScan({ targetedFormats: [SupportedFormat.QR_CODE] }); // start scanning and wait for a result // if the result has content if (result.hasContent) { console.log(result.content); // log the raw scanned content this.renderer.removeClass(document.body, 'scanner-active'); } }
// global.scss body.scanner-active { --background: transparent; --ion-background-color: transparent; opacity: 0; // Add this line is global.scss file }
Hope this will solve the problem.
Tks
If you are using vue.js 3, you can set it like this within the component itself, without having to do it globally like @GeekSankha tip
:global(body.barcode-scanning-active) {
--background: transparent;
--ion-background-color: transparent;
}
I already added the body.scanner-active { --background: transparent; --ion-background-color: transparent; }
and the permission is granted. Can someone please help me