HarmonyOS5 便捷生活类——如何实现长按识别H5页面的二维码图片

加入下方官方优快云班级,得鸿蒙礼盒

一起拿鸿蒙礼盒,戳我戳我!!

本期活动时间:2025年8月1日-12月31日

如有问题欢迎私聊我呀!


问题现象

当前在H5页面长按二维码图片会触发拖拽动作,如何禁用图片拖拽事件并实现长按识别H5页面的二维码图片。

背景知识

解决方案

长按识别H5页面的二维码图片实现步骤如下:

  1. 通过runJavaScript禁用图片的拖拽事件。
  2. 通过onContextMenuShow监听图片的长按事件并获取到图片的url。
  3. 根据URL获取网络图片数据并通过detectBarcode.decodeImage接口识别图片中的二维码。
  • Web组件绑定onContextMenuShow监听图片长按事件,获取图片的url并解码。
     
    import web_webview from '@ohos.web.webview';
    import promptAction from '@ohos.promptAction';
    import { BusinessError } from '@ohos.base';
    import { http } from '@kit.NetworkKit';
    import { image } from '@kit.ImageKit';
    import { detectBarcode, scanBarcode, scanCore } from '@kit.ScanKit';
    @Entry
    @Component
    struct WebQRScanner {
    controller: web_webview.WebviewController = new web_webview.WebviewController();
    build() {
    Column() {
    Web({ src: 'https://example.com', controller: this.controller })
    .onPageEnd(() => {
    // 禁用图片拖拽
    this.disableDragScript();
    })
    .onContextMenuShow((event) => {
    if (event.param.getMediaType() === ContextMenuMediaType.Image) {
    // 获取图片并识别二维码
    this.scanQRFromWebImage(event.param.getSourceUrl());
    return false;
    }
    return true;
    })
    }
    }
    }

  • 禁用H5中图片的拖拽事件。
     
    disableDragScript() {
    const jsCode = `
    var images = document.getElementsByTagName('img');
    for (var i = 0; i < images.length; i++) {
    images[i].draggable = false;
    }
    true;
    `;
    this.controller.runJavaScript(jsCode, (error: BusinessError) => {
    if (error) {
    console.error('注入JavaScript失败:', error);
    }
    });
    }

  • 根据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) {
    promptAction.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) {
    promptAction.showToast({ message: result });
    } else {
    promptAction.showToast({ message: '识别失败' });
    }
    // 释放资源
    pixelMap.release();
    imageSource.release();
    } catch (error) {
    const err = error as BusinessError;
    promptAction.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) => {
    return 'code' + error.code + 'message' + error.message
    });
    } catch (error) {
    return 'code' + error.code + 'message' + error.message
    }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值