以下の内容はhttps://www.wheatandcat.me/entry/2024/10/22/195318より取得しました。


バーコード読み込んで商品画像を取得する機能を実装

引越しをしていて間が空いてしまったが、次から通常の更新頻度に戻る予定

在庫管理アプリの開発で商品の画像取得に商品検索(v3) - Yahoo!デベロッパーネットワークのAPIを使ってみたので紹介

PR

github.com

github.com

実装

実装のイメージは以下の通り - アプリでバーコード読み取り画面を実装 - バーコードのJANコードをbackendに渡して、商品検索(v3)APIで商品の情報を取得

まずはbackendの実装。JANコードから商品情報の取得はYahooが提供している以下のAPIから取得可能。

developer.yahoo.co.jp

APIは簡単でような感じで商品情報を取得できる

curl --location 'https://shopping.yahooapis.jp/ShoppingWebService/V3/itemSearch?appid=*****&jan_code=4901777062702&image_size=300'

※appidの部分は自分のアカウントのアプリケーションのClient IDを設定

レスポンスは以下みたいに返ってくる

上記のAPIを使用して以下のPRでbackendのAPIを作成

github.com

次にアプリ側の実装。バーコードをスキャンしてJANコードを取得するためにmobile_scannerを使用

pub.dev

実装は以下の通り

dart/app/lib/features/item/new/components/barcodeScannerScreen.dart

import 'package:mobile_scanner/mobile_scanner.dart';

(略)

  @override
  Widget build(BuildContext context) {
    final cameraController = useMemoized(() => MobileScannerController());

    // アニメーションコントローラを定義(ここでは3秒でスキャンラインが1サイクル)
    final animationController = useAnimationController(
      duration: const Duration(seconds: 2),
    )..repeat(reverse: true); // 繰り返しアニメーションを実行

    return Scaffold(
      appBar: const CommonAppBar(title: ""),
      body: Stack(
        children: [
          // カメラでのバーコード読み取り
          MobileScanner(
            controller: cameraController,
            onDetect: onScan,  // バーコードを読み込んだ時に、onScanを実行
          ),

dart/app/lib/app/items/new/page.dart

    Future<void> onScan(BarcodeCapture capture) async {
      final List<Barcode> barcodes = capture.barcodes;
      final value = barcodes.first.rawValue;

      if (value != null && barcodes.first.format == BarcodeFormat.ean13) {
        final String code = value;
        print('Scanned JAN code: $code');  // ここでスキャンしたバーコード情報からJANコードを取得できる

        final result = await client.query<Query$ItemFromQR>(QueryOptions(
            document: documentNodeQueryItemFromQR,
            variables: {'janCode': code}));

        if (result.hasException) {
          debugPrint(result.exception.toString());
          scan.value = true;
          return;
        }

        defaultValue.value = InputItem(
          name: result.data!['itemFromQR']['name'],
          imageURL: result.data!['itemFromQR']['imageURL'],
          stock: 0,
          order: 0,
        );

        scan.value = true;
      }
    }

上記でバーコードからJANコードを読み込んで商品情報が取得できるようになった

このままだとカメラ起動時にバーコードを読み取らせている感が薄かったので、ChatGPTにアニメーションを作らせて以下のコードになった

dart/app/lib/features/item/new/components/barcodeScannerScreen.dart

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:stockkeeper/components/appBar/common.dart';

class BarcodeScannerScreen extends HookWidget {
  final Future<void> Function(BarcodeCapture capture) onScan;

  const BarcodeScannerScreen({
    super.key,
    required this.onScan,
  });

  @override
  Widget build(BuildContext context) {
    final cameraController = useMemoized(() => MobileScannerController());

    // アニメーションコントローラを定義(ここでは3秒でスキャンラインが1サイクル)
    final animationController = useAnimationController(
      duration: const Duration(seconds: 2),
    )..repeat(reverse: true); // 繰り返しアニメーションを実行

    return Scaffold(
      appBar: const CommonAppBar(title: ""),
      body: Stack(
        children: [
          // カメラでのバーコード読み取り
          MobileScanner(
            controller: cameraController,
            onDetect: onScan,
          ),
          // スキャンエリアのオーバーレイ
          CustomPaint(
            size: MediaQuery.of(context).size,
            painter: ScannerOverlay(),
          ),
          // スキャンラインのアニメーション
          AnimatedBuilder(
            animation: animationController,
            builder: (context, child) {
              // アニメーションの進行に基づいてスキャンラインの位置を計算
              final position = animationController.value * 300; // 0から300まで移動
              return Positioned(
                top: MediaQuery.of(context).size.height * 0.22 + position,
                left: 40,
                right: 40,
                child: child!,
              );
            },
            child: Container(
              height: 2,
              color: Colors.redAccent,
            ),
          ),
        ],
      ),
    );
  }
}

class ScannerOverlay extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.black.withOpacity(0.5)
      ..style = PaintingStyle.fill;

    // スクリーン全体を半透明で塗りつぶす
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);

    // スキャンエリア(中央部分の透明な四角形)
    paint.color = Colors.transparent;
    final scanRect = Rect.fromLTWH(40, size.height / 4, size.width - 80, 300);
    canvas.drawRect(scanRect, paint);

    // スキャンエリアの枠線を描く
    final borderPaint = Paint()
      ..color = Colors.white
      ..strokeWidth = 3
      ..style = PaintingStyle.stroke;

    canvas.drawRect(scanRect, borderPaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

これらを実装して以下みたいな動作が完成

www.youtube.com




以上の内容はhttps://www.wheatandcat.me/entry/2024/10/22/195318より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14