LoginSignup
16
8

More than 3 years have passed since last update.

【Flutter】Flutter製アプリをリリースしてみた、あとARとかも使ってみた話

Last updated at Posted at 2020-05-28

アプリ概要

ゴルフのオリンピックゲームの計算やボールとピンまでの距離のAR測定,1−18までの乱数を生成することができる、ゴルフ幹事向けのアプリです。

App Store はこちら
Google Play Store はこちら

image.png

ファイル名ファイル名ファイル名

使用した技術

  • bloc
  • Provider
  • rxDart
  • Admob
  • Firebase Analytics
  • ARKit(iOSのみ)

ソースコードはこちら

https://github.com/Tetsukick/enGolf

AR技術のご紹介

iPhoneのみARKitを活用したプラグイン(arkit_flutter)が公開されていたので、そちらを活用して、タップした2点間の距離を測れるアプリを作成いたしました。

AR距離測定画面のソースコードを記載しておきます。
Sampleを80%ぐらい流用して簡単に開発できました。

import 'package:arkit_plugin/arkit_plugin.dart';
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' as vector;

import 'dart:io';

class ARMeasureScreen extends StatefulWidget {
  @override
  _ARMeasureScreen createState() => _ARMeasureScreen();
}

class _ARMeasureScreen extends State<ARMeasureScreen> {
  ARKitController arkitController;
  vector.Vector3 lastPosition;

  @override
  void dispose() {
    arkitController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context){
    return Platform.isIOS ? Scaffold(
      body: Container(
        child: ARKitSceneView(
          enableTapRecognizer: true,
          onARKitViewCreated: onARKitViewCreated,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.delete),
        backgroundColor: Colors.lightGreen,
        onPressed: () {
          arkitController.remove('point');
          arkitController.remove('text');
          arkitController.remove('line');
          lastPosition = null;
        },
      ),
    ) :
    Scaffold(
      body: Center(
        child: Text('Androidには対応しておりません\n現在開発中のためしばらくお待ち下さい。'),
      ),
    );
  }

  void onARKitViewCreated(ARKitController arkitController) {
    this.arkitController = arkitController;
    this.arkitController.onARTap = (ar) {
      final point = ar.firstWhere(
            (o) => o.type == ARKitHitTestResultType.featurePoint,
        orElse: () => null,
      );
      if (point != null) {
        _onARTapHandler(point);
      }
    };
  }

  void _onARTapHandler(ARKitTestResult point) {
    final position = vector.Vector3(
      point.worldTransform.getColumn(3).x,
      point.worldTransform.getColumn(3).y,
      point.worldTransform.getColumn(3).z,
    );
    final material = ARKitMaterial(
        lightingModelName: ARKitLightingModel.constant,
        diffuse: ARKitMaterialProperty(color: Colors.blue));
    final sphere = ARKitSphere(
      radius: 0.006,
      materials: [material],
    );
    final node = ARKitNode(
      name: 'point',
      geometry: sphere,
      position: position,
    );
    arkitController.add(node);

    if (lastPosition != null) {
      final line = ARKitLine(
        fromVector: lastPosition,
        toVector: position,
      );
      final lineNode = ARKitNode(
          name: 'line',
          geometry: line
      );
      arkitController.add(lineNode);

      final distance = _calculateDistanceBetweenPoints(position, lastPosition);
      final point = _getMiddleVector(position, lastPosition);
      _drawText(distance, point);
    }
    lastPosition = position;
  }

  String _calculateDistanceBetweenPoints(vector.Vector3 A, vector.Vector3 B) {
    final length = A.distanceTo(B);
    return '${(length * 100).toStringAsFixed(2)} cm';
  }

  vector.Vector3 _getMiddleVector(vector.Vector3 A, vector.Vector3 B) {
    return vector.Vector3((A.x + B.x) / 2, (A.y + B.y) / 2, (A.z + B.z) / 2);
  }

  void _drawText(String text, vector.Vector3 point) {
    final textGeometry = ARKitText(
      text: text,
      extrusionDepth: 1,
      materials: [
        ARKitMaterial(
          diffuse: ARKitMaterialProperty(color: Colors.red),
        )
      ],
    );
    const scale = 0.001;
    final vectorScale = vector.Vector3(scale, scale, scale);
    final node = ARKitNode(
      name: 'text',
      geometry: textGeometry,
      position: point,
      scale: vectorScale,
    );
    arkitController.add(node);
  }
}

16
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
8