接到一個app的改造的任務,主要是適配一款手持設備,在頁面上增加一個類似微信的二維碼掃描的喚醒按鈕,點擊之後進入掃描二維碼的頁面————
步驟如下:
1、在項目中下載QRCode的cordova插件:
ionic cordova plugin add codova-plugin-qrscanner
2、下載QRScanner插件:
npm install --save @ionic-native/qr-scanner
這裏要注意一下你下載的qr-scanner版本是什麼,就我的來說,4.0+的版本的引入和5.0+的版本引入有一些區別,導致我調試了好久才發現引入的問題;
3、創建一個掃描儀頁面,整個頁面都是拿來作掃描的界面,這個界面在調用qrscanner對象的scan方法,此方法會返回文本掃描的Observable,使用訂閱subscribe,scanner對象的調用unsubscribe將會取消訂閱;
這個頁面我是這樣做的——————
1️⃣qrscanner.html:
<ion-header>
<page-header>掃描二維碼</page-header>
</ion-header>
<ion-content [ngClass]="{'qrscannerMenu':isShow}">
<div class="area"></div>
<div class="line"></div>
</ion-content>
<ion-footer>
<div class="warp-icon" tappable (click)="toggleCamera()">
<img src="assets/imgs/qrscanner/camera.svg" style="height:55%">
</div>
<div class="warp-icon" tappable (click)="toggleLight()">
<img src="assets/imgs/qrscanner/flashlight.svg" style="height:60%">
</div>
</ion-footer>
2️⃣qrscanner.ts:
import { Component, forwardRef, Inject } from '@angular/core';
import { Events, IonicPage, NavController } from 'ionic-angular';
import { QRScanner, QRScannerStatus } from '@ionic-native/qr-scanner/ngx';
import { NativeService } from '../../../providers/scan/NativeService';
/**
* 掃描二維碼
* @example
this.navCtrl.push('QrscannerPage').then(() => {
this.events.subscribe('qrscanner:result', text => {
alert('掃描結果:' + text);
});
});
*/
@IonicPage()
@Component({
selector: 'page-qrscanner',
templateUrl: 'qrscanner.html',
})
export class QrscannerPage {
light: boolean = false; // 判斷閃光燈
isShow: boolean = false; // 控制顯示背景,避免切換頁面卡頓
constructor(
private navCtrl: NavController,
private nativeService: NativeService,
private events: Events,
// **如果沒有注意版本問題,引入的方式錯誤,下面的依賴會報錯:
// Error: Can't resolve all parameters for QrscannerPage: ([object Object], [object Object], [object Object], ?).
private qrScanner: QRScanner,
) { }
ionViewDidLoad() {
if (!this.nativeService.isMobile()) {
alert('請使用真機調試');
return;
}
this.qrScanner.prepare().then((status: QRScannerStatus) => {
if (status.authorized) { // 判斷是否有攝像頭權限
let scanSub = this.qrScanner.scan().subscribe((text: string) => {
this.events.publish('qrscanner:result', text);
scanSub.unsubscribe();
this.navCtrl.pop();
});
// 打開攝像頭
this.qrScanner.show();
} else if (status.denied) {
alert('沒有攝像頭權限,請前往設置中開啓');
} else {
alert('沒有攝像頭權限,請前往設置中開啓');
}
}).catch((e: any) => console.log('調用二維碼掃描插件失敗', e));
}
ionViewWillEnter() {
(window.document.querySelector('ion-app') as HTMLElement).classList.add('cameraView'); // tslint:disable-line
this.isShow = true; // 顯示背景
}
ionViewWillLeave() {
(window.document.querySelector('ion-app') as HTMLElement).classList.remove('cameraView'); // tslint:disable-line
this.qrScanner.hide(); // 需要關閉掃描,否則相機一直開着
this.qrScanner.destroy(); // 關閉
this.events.unsubscribe('qrscanner:result'); // 退出頁面取消所有訂閱,進入頁面前需訂閱
}
/* 切換前後攝像頭 */
toggleCamera() {
if (this.frontCamera) {
this.qrScanner.useBackCamera();
} else {
this.qrScanner.useFrontCamera();
}
this.frontCamera = !this.frontCamera;
}
// 開關手電筒
toggleLight() {
this.light ? this.qrScanner.disableLight() : this.qrScanner.enableLight();
this.light = !this.light;
}
}
注意上面的QRScanner這個依賴,我使用的QRScanner插件的版本是5.0+的版本(5.25.0版本),在它的依賴目錄裏面qr-scanner,index.d.ts中,QRScanner這個依賴不是作爲類輸出的,所以我們應該在頁面上引用qr-scanner的ngx文件夾中的index.d.ts中輸出的QRScanner類:
3️⃣qrscanner.module.ts:
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { QrscannerPage } from './qrscanner';
import { ComponentsModule } from '../../components/components.module';
@NgModule({
imports: [
ComponentsModule,
IonicPageModule.forChild(QrscannerPage),
],
declarations: [
QrscannerPage,
],
})
export class QrscannerPageModule {
}
4️⃣qrscanner.scss:
ion-app.cameraView,
ion-app.cameraView ion-content,
ion-app.cameraView .nav-decor {
background: transparent none !important;
.tabbar.show-tabbar {
opacity: 0;
}
}
page-qrscanner {
.qrscannerMenu {
background: none transparent;
.area {
margin-top: 30px;
width: 100%;
height: 90%;
background: url(../assets/imgs/qrscanner/scanner.svg) no-repeat center center;
background-size: contain;
}
.line {
left: 25%;
width: 50%;
height: 2px;
background: red;
position: absolute;
animation: myfirst 2s linear infinite alternate;
}
@keyframes myfirst {
0% {
background: red;
top: 34%;
}
25% {
background: yellow;
top: 40%;
}
50% {
background: blue;
top: 46%;
}
75% {
background: green;
top: 52%;
}
100% {
background: red;
top: 60%;
}
}
}
ion-footer {
display: flex;
justify-content: space-around;
padding: 22px;
.warp-icon {
width: 45px;
height: 45px;
background: #0071ff;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
span {
position: absolute;
margin-top: 38px;
font-size: 12px;
color: #fff;
}
}
}
}
以上的這個組件作爲一個封裝好的頁面,可以一次封裝,到處引用。
4、注意要在app.module.ts中引入QRScanner依賴:
import { QRScanner } from '@ionic-native/qr-scanner/ngx';
providers: [
QRScanner,
.....
]
5、variables.scss:
在後面增加樣式,用於掃碼的頁面透明顯示:
ion-app.cameraView,
ion-app.cameraView ion-content,
ion-app.cameraView .nav-decor {
background: transparent none !important;
.tabbar.show-tabbar {
opacity: 0;
}
}
6、index.html中,需要修改<ion-app>的內容:需要設置背景爲透明
<ion-app style="background: none transparent;"></ion-app>
7、AndroidManifest.xml文件中,配置相機、手電筒等的調用權限:
增加如下代碼:
<!-- 二維碼掃描 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.INTERNET" />
______________________________________________________
下面開始使用上面封裝的掃碼頁面:
在需要使用的頁面上,直接跳轉到掃碼頁面上即可:
在html上增加掃碼入口按鈕:
<button ion-button (click)="showScanner()" style="float: right;height: 30px;margin-top:10px;width:10%">
<ion-icon ios="ios-qr-scanner" md="md-qr-scanner"></ion-icon>
</button>
在ts上跳轉頁面:
showScanner() {
this.navCtrl.push('QrscannerPage').then(() => {
this.events.subscribe('qrscanner:result', text => {
// 可以將掃描的結果text拿去使用啦
});
});
}
——————————————————————————————————————
附上scss中用到的圖片素材,自己放到自己項目的圖片文件夾中:
——————————————————————————————————————
由於廠商的設備還沒有寄到我手上,所以暫時沒有辦法調試,現在在筆記本本地調試的效果如下,頁面顯示暫時沒有辦法正常展示,大家可以作爲參考(更新後可以正常使用,請參考下方2020.05.22的更新):
_________________________________________________________________________________
2020.05.22更新:
這兩天一直在調試設備上的QRScanner掃碼的問題,首先交代一下我的本地環境:
--------------------- ---------------------- ------------------------ ----------------------
node v10.16.3
android Android SDK Manager上相關配置見下圖:
ionic 5.4.16
--------------------- ---------------------- ------------------------ ----------------------
之前我安裝的QRScanner版本是5.25.0的;
cordova-plugin-qrscanner是3.1.0版本的。
雖然引入沒什麼問題,但是所有的方法,qrscanner.prepare()、qrscanner.show().....都會報錯:
ERROR TypeError: Object(...) is not a function
所以我懷疑可能是版本不匹配的問題,下載安裝其他的QRScanner版本試試看——
接下來我們先將QRScanner插件卸載:
npm uninstall @ionic-native/qr-scanner
重新安裝插件,這一次我們選擇安裝低版本的QRScanner插件:
ionic cordova plugin add [email protected]
npm install @ionic-native/[email protected]
安裝成功之後,我們要將封裝好的掃描頁面和其他引入了QRScanner插件的頁面上的引入方式改一下:
import { QRScanner, QRScannerStatus } from '@ionic-native/qr-scanner';
這樣引入之後,可以正常使用了,掃描的效果見下圖: