cordova-plugin-qrscanner可以高度定制扫码页面UI,相比于phonegap-plugin-barcodescanner来说,速度也快,
新建扫码页面qr-scanner:
html:
<ion-header>
<ion-toolbar class="scanner">
<ion-buttons slot="start">
<ion-button (click)="closeModal()">
<ion-icon slot="icon-only" name="close"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>扫描中</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [class.scanner]="scannerClass">
<div class="qr-scanner-area">
<p class="lines"></p>
</div>
<ion-grid fixed class="scanner-button-bottom">
<ion-row>
<ion-col size="6" class="ion-flex ion-justify-content-center">
<ion-button fill="clear" class="qr-scanner-button" (click)="toogleLight()">
<ion-icon slot="icon-only" [name]="lightIcon"></ion-icon>
</ion-button>
</ion-col>
<ion-col size="6" class="ion-flex ion-justify-content-center">
<ion-button fill="clear" class="qr-scanner-button" (click)="toggleCamera()">
<ion-icon name="reverse-camera" slot="icon-only"></ion-icon>
</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
css:
.scanner{ // 一定要将ion-content设置为背景透明,否则看不到摄像头画面
--background: none transparent !important;
background: none transparent !important;
--color: white;
ion-icon{
color: white;
font-size: 20px;
}
}
.scanner-button-bottom{
position: absolute;
bottom: 45px;
left: auto;
right: auto;
width: 100%;
.qr-scanner-button{
width: 75px;
height: 75px;
border-radius: 100%;
background: rgba(0, 0, 0, 0.3);
}
}
.qr-scanner-area{
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: calc(100% - 45px - 103px);
background: url('./../../../assets/icon/qrscanner/scanner.svg') no-repeat center ;
background-size: 100% 100%;
.lines{
width: 58%;
height: 2px;
background: var(--ion-color-primary);
animation: lines 2s linear infinite alternate;
}
}
TS:
import { NavController, Platform } from '@ionic/angular';
import { ModalsService } from './../../service/modals/modals.service';
import { QRScanner, QRScannerStatus } from '@ionic-native/qr-scanner/ngx';
import { Component, OnDestroy, ElementRef } from '@angular/core';
import { ComponentsServiceService } from './../../service/componentsService/components-service.service';
@Component({
selector: 'app-qr-scanner',
templateUrl: './qr-scanner.page.html',
styleUrls: ['./qr-scanner.page.scss'],
})
export class QrScannerPage implements OnDestroy {
lightIcon: string;
light: boolean;
frontCamera: boolean;
scannerClass: boolean;
constructor(
private platform: Platform,
private scanner: QRScanner,
private router: NavController,
private modal: ModalsService,
private element: ElementRef,
private messageService: ComponentsServiceService,
) {
this.lightIcon = 'flash-off';
this.modal.showLoading();
}
ionViewDidEnter() {
this.modal.hideLoading();
this.scannerClass = true;
this.startScanner();
this.scanner.show();
}
ngOnDestroy() {
this.scannerClass = false;
this.destroyScanner();
}
closeModal() {
this.router.back();
this.destroyScanner();
}
toogleLight() {
this.light = !this.light;
if (this.light) {
this.lightIcon = 'flash';
this.scanner.enableLight();
} else {
this.lightIcon = 'flash-off';
this.scanner.disableLight();
}
}
toggleCamera() {
this.frontCamera = !this.frontCamera;
if (this.frontCamera) {
this.scanner.useFrontCamera();
} else {
this.scanner.useBackCamera();
}
}
startScanner() {
this.platform.ready().then(() => {
this.scanner.destroy();
// Optionally request the permission early
this.scanner.prepare().then((status: QRScannerStatus) => {
if (status.authorized) {
// camera permission was granted
// start scanning
let scanSub = this.scanner.scan().subscribe((text: string) => {
console.log(text);
this.messageService.sendEvents({ type: 'scanner', data: text });
this.scanner.hide(); // hide camera preview
scanSub.unsubscribe(); // stop scanning
this.router.back();
});
} else if (status.denied) {
this.scanner.openSettings();
// camera permission was permanently denied
// you must use QRScanner.openSettings() method to guide the user to the settings page
// then they can grant the permission from there
} else {
// permission was denied, but not permanently. You can ask for permission again at a later time.
}
}).catch((e: any) => this.modal.toast(e));
});
}
destroyScanner() {
this.scanner.destroy();
// 这里延迟一秒将html背景色重新设置为白色,否则会变透明,影响视觉效果
setTimeout(() => {
(window.document.querySelector('html') as HTMLElement).style.backgroundColor = '#fff';
}, 1000);
}
}
至此,便可以真机调试扫描二维码,此插件默认是只能扫描二维码的,也就是QR码,如果需要扫描条形码,也就是一维码,需要在源码里添加格式支持:
Android:plugins/cordova-plugin-qrscanner/src/android/QRScanner.java找到458行添加以下内容:
formatList.add(BarcodeFormat.UPC_A);
formatList.add(BarcodeFormat.UPC_E);
formatList.add(BarcodeFormat.EAN_13);
formatList.add(BarcodeFormat.EAN_8);
formatList.add(BarcodeFormat.CODE_39);
formatList.add(BarcodeFormat.CODE_93);
formatList.add(BarcodeFormat.CODE_128);
formatList.add(BarcodeFormat.ITF);
formatList.add(BarcodeFormat.DATA_MATRIX);
IOS:plugins/cordova-plugin-qrscanner/src/ios/QRScanner.swift :
// 第156行修改为
metaOutput!.metadataObjectTypes = [AVMetadataObject.ObjectType.qr, AVMetadataObject.ObjectType.code39, AVMetadataObject.ObjectType.code93, AVMetadataObject.ObjectType.code128, AVMetadataObject.ObjectType.dataMatrix,
AVMetadataObject.ObjectType.ean8, AVMetadataObject.ObjectType.ean13]
// 第243行修改为
if (found.type == AVMetadataObject.ObjectType.qr || found.type == AVMetadataObject.ObjectType.code39
|| found.type == AVMetadataObject.ObjectType.code93 || found.type == AVMetadataObject.ObjectType.code128
|| found.type == AVMetadataObject.ObjectType.dataMatrix || found.type == AVMetadataObject.ObjectType.ean8
|| found.type == AVMetadataObject.ObjectType.ean13) && found.stringValue != nil {
............
}
修改完后,需要重新添加IOS、Android平台才可生效。