长按识别H5页面的二维码图片实现步骤如下:
样例代码如下:
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
import { http } from '@kit.NetworkKit';
import { image } from '@kit.ImageKit';
import { detectBarcode, scanBarcode, scanCore } from '@kit.ScanKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct WebRecognizeQRcode {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
// src需要替换为带有二维码图片的网址
Web({ src: 'www.example.com', controller: this.controller })
.onPageEnd(() => {
// 禁用图片拖拽
this.executeDisableDragScript();
})
.onContextMenuShow((event) => {
if (event.param.getMediaType() === ContextMenuMediaType.Image) {
// 获取图片并识别二维码
this.scanQRFromWebImage(event.param.getSourceUrl());
event.result.closeContextMenu();
}
return true;
})
.fileAccess(false)
.geolocationAccess(false)
.domStorageAccess(true);
};
}
/**
* 禁用H5中图片的拖拽事件
*/
executeDisableDragScript() {
const jsCode = `
// 禁用所有图片拖拽
const images = document.getElementsByTagName('img');
for (let i = 0; i < images.length; i++) {
images[i].draggable = false;
}
// 监听动态加载的图片
new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.tagName === 'IMG') {
node.draggable = false;
}
});
});
}).observe(document.body, { childList: true, subtree: true });
`;
this.controller.runJavaScript(jsCode, (error: BusinessError) => {
if (error) {
hilog.error(0x0001, 'runJavaScript', `执行JavaScript失败: ${error.message}`);
}
});
}
/**
* 根据url获取网络图片数据。
*/
private async downloadImage(url: string): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
const httpRequest = http.createHttp();
httpRequest.request(
url,
{
method: http.RequestMethod.GET,
expectDataType: http.HttpDataType.ARRAY_BUFFER
},
(err, data) => {
if (err) {
reject(new Error(`图片获取失败: ${err.message}`));
return;
}
if (data && data.result) {
resolve(data.result as ArrayBuffer);
} else {
reject(new Error('未获取到图片数据'));
}
}
);
});
}
/**
* 识别图中二维码。
*/
async scanQRFromWebImage(url: string) {
this.getUIContext().getPromptAction().showToast({ message: '开始识别二维码...' });
try {
// 1.下载网络图片
const imageData = await this.downloadImage(url);
// 2.创建ImageSource
const imageSource = image.createImageSource(imageData);
const pixelMap = await imageSource.createPixelMap();
// 3.二维码识别
const result = await this.decodeImageBuffer(pixelMap);
if (result) {
this.getUIContext().showAlertDialog({
message: result
});
} else {
this.getUIContext().getPromptAction().showToast({ message: '识别失败' });
}
// 4.释放资源
pixelMap.release();
imageSource.release();
} catch (error) {
const err = error as BusinessError;
this.getUIContext().getPromptAction().showToast({ message: err.message });
}
}
async decodeImageBuffer(pixelMap: image.PixelMap) {
pixelMap.convertPixelFormat(image.PixelMapFormat.NV12);
let info = await pixelMap.getImageInfo();
let pixelBytesNumber: number = pixelMap.getPixelBytesNumber();
let buffer = new ArrayBuffer(pixelBytesNumber);
await pixelMap.readPixelsToBuffer(buffer);
let byteImg: detectBarcode.ByteImage = {
byteBuffer: buffer,
width: info.size.width,
height: info.size.height,
format: detectBarcode.ImageFormat.NV21
};
let options: scanBarcode.ScanOptions =
{ scanTypes: [scanCore.ScanType.ALL], enableMultiMode: true, enableAlbum: false };
try {
return detectBarcode.decodeImage(byteImg, options).then((result: detectBarcode.DetectResult) => {
return JSON.stringify(result);
}).catch((error: BusinessError) => {
hilog.error(0x0001, '[ScanCode]',
`Failed to get DetectResult by promise with options. Code: ${error.code}, message: ${error.message}`);
});
} catch (error) {
hilog.error(0x0001, '[ScanCode]',
`Failed to get DetectResult by promise with options. Code: ${error.code}, message: ${error.message}`);
}
}
}