Flutter二维码扫描插件jsqr的使用

Flutter二维码扫描插件jsqr的使用

jsqr_flutter 是一个用于 Flutter 的二维码扫描库。它基于 jsqr 库来识别二维码。

注意: 此插件仅适用于 Flutter Web。

使用方法

web/index.html 文件中添加以下脚本:

<script src="https://cdn.jsdelivr.net/npm/jsqr@1.3.1/dist/jsQR.min.js"></script>

pubspec.yaml 文件中添加以下依赖:

dependencies:
  jsqr: ^0.1.1

扫描二维码

示例代码:

var code = await showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            insetPadding: EdgeInsets.all(5),
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10.0))),
            title: const Text('Scan QR Code'),
            content: Container(
                width: 640,
                height: 480,
                child: Scanner()),
          );
        });

code 变量将包含二维码中的数据。

图像捕获

你也可以通过传递 clickToCapture: true 来捕获图像。以下是一个完整的示例:

import 'package:flutter/material.dart';
import 'package:jsqr/scanner.dart';
import 'dart:html' as html;
import 'dart:ui' as ui;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String code;
  Future<bool> camAvailableF;
  html.ImageElement img;

  [@override](/user/override)
  void initState() {
    super.initState();
    camAvailableF = Scanner.cameraAvailable();
  }

  void _openScan() async {
    var code = await showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            insetPadding: EdgeInsets.all(5),
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10.0))),
            title: const Text('Scan QR Code'),
            content: Container(
                width: 640,
                height: 480,
                child: Scanner()),
          );
        });
    print("CODE: $code");
    setState(() {
      this.code = code;
      _counter++;
    });
  }

  void _captureImage() async {
    var dataUrl = await showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            insetPadding: EdgeInsets.all(5),
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10.0))),
            title: const Text('Scan QR Code'),
            content: Container(
                width: 640,
                height: 480,
                child: Scanner(
                  clickToCapture: true,
                )),
          );
        });
    print("IMG URL: $dataUrl");
    html.DivElement vidDiv = html.DivElement();

    ui.platformViewRegistry.registerViewFactory("cap", (int id) => vidDiv);

    img = new html.ImageElement();
    img.src = dataUrl;
    vidDiv.children = [img];

    setState(() {
      _counter++;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            FutureBuilder<bool>(
              future: camAvailableF,
              builder: (context, snapshot) {
                if (snapshot.hasError) {
                  return Text("ERROR: ${snapshot.error}");
                }
                if (snapshot.hasData) {
                  if (snapshot.data) {
                    return Text("Camera is available");
                  }
                  return Text("No camera available");
                } else {
                  return CircularProgressIndicator();
                }
              },
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            Text(
              '$code',
              style: Theme.of(context).textTheme.headline4,
            ),
            SizedBox(height: 10),
            RaisedButton(
              child: Text("Scan QR Code"),
              onPressed: _openScan,
            ),
            SizedBox(height: 10),
            RaisedButton(
              child: Text("Capture Image"),
              onPressed: _captureImage,
            ),
            SizedBox(height: 10),
            if (img != null)
              SizedBox(
                  width: 640,
                  height: 480,
                  child: HtmlElementView(viewType: "cap")),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter二维码扫描插件jsqr的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter二维码扫描插件jsqr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在 Flutter 中使用 jsqr 插件进行二维码扫描是一个相对简单的过程。jsqr 是一个用于解码二维码的 JavaScript 库,虽然它本身不是 Flutter 插件,但你可以通过 Flutter 的 webview_flutter 插件将 jsqr 集成到你的应用中。

以下是一个简单的步骤指南,展示如何在 Flutter 应用中使用 jsqr 进行二维码扫描:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 webview_flutter 依赖:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.0.0

2. 创建 HTML 文件

在你的 Flutter 项目中创建一个 HTML 文件,例如 qr_scanner.html,并在其中引入 jsqr 库。你可以使用 CDN 来引入 jsqr

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>QR Code Scanner</title>
    <script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>
</head>
<body>
    <video id="video" width="100%" height="100%" autoplay></video>
    <canvas id="canvas" style="display:none;"></canvas>
    <script>
        const video = document.getElementById('video');
        const canvas = document.getElementById('canvas');
        const context = canvas.getContext('2d');

        navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } })
            .then((stream) => {
                video.srcObject = stream;
                video.play();
                requestAnimationFrame(tick);
            });

        function tick() {
            if (video.readyState === video.HAVE_ENOUGH_DATA) {
                canvas.height = video.videoHeight;
                canvas.width = video.videoWidth;
                context.drawImage(video, 0, 0, canvas.width, canvas.height);
                const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
                const code = jsQR(imageData.data, imageData.width, imageData.height, {
                    inversionAttempts: "dontInvert",
                });
                if (code) {
                    window.flutter_inappwebview.callHandler('qrCodeScanned', code.data);
                }
            }
            requestAnimationFrame(tick);
        }
    </script>
</body>
</html>

3. 在 Flutter 中加载 HTML 文件

在 Flutter 中使用 webview_flutter 加载上面创建的 HTML 文件,并监听二维码扫描结果:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class QRScannerScreen extends StatefulWidget {
  @override
  _QRScannerScreenState createState() => _QRScannerScreenState();
}

class _QRScannerScreenState extends State<QRScannerScreen> {
  late WebViewController _webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('QR Code Scanner'),
      ),
      body: WebView(
        initialUrl: 'asset://assets/qr_scanner.html',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          _webViewController = webViewController;
          _webViewController.addJavaScriptHandler('qrCodeScanned', (data) {
            // 处理扫描到的二维码数据
            print('Scanned QR Code: $data');
            Navigator.pop(context, data);
          });
        },
      ),
    );
  }
}

4. 运行应用

确保你的 HTML 文件在 assets 文件夹中,并在 pubspec.yaml 中声明:

flutter:
  assets:
    - assets/qr_scanner.html

然后运行你的 Flutter 应用,你应该能够看到一个二维码扫描界面,并且扫描到的二维码数据会被打印到控制台。

5. 处理扫描结果

在上面的代码中,我们使用 Navigator.pop 将扫描结果返回到上一个页面。你可以在调用 QRScannerScreen 的地方处理这个结果:

void _scanQRCode(BuildContext context) async {
  final result = await Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => QRScannerScreen()),
  );
  if (result != null) {
    // 处理扫描结果
    print('Scanned QR Code: $result');
  }
}
回到顶部