🦔

Flutterで過去の地震の震度を可視化する

2024/07/02に公開

概要

Flutterの勉強のため、マップ上に地震情報をアニメーション表示するアプリを作成しました。
学習記録を残します。

成果物

GitHub

https://github.com/Nyamadamadamada/earthquake_map/tree/main

がんばったところ

Provider

地震情報、タイマーの値、マップのマーカーの値など、Widgetをまたぐ動的な値はすべてProviderで管理しました。

/// <<<Providerの定義>>>
// タイムシークの現在の値(インデックス)
class CurrentYearMonthIndexNotifier extends StateNotifier<int> {
  CurrentYearMonthIndexNotifier() : super(0);
  // 直接値を変える
  void set(int index) {
    state = index;
  }
   // 1づつ増やす
  void increment() {
    state = state + 1;
  }
}

final currentYearMonthIndexProvider =
    StateNotifierProvider<CurrentYearMonthIndexNotifier, int>((ref) {
  return CurrentYearMonthIndexNotifier();
});

/// <<<利用シーン>>>
ref.read(currentYearMonthIndexProvider.notifier).increment();

Freezed

地震情報をJSONで保管しており、JSONデータをFlutterのクラスとして使うため、freezedを使用しました。
EarthquakeクラスのfromJson()でJSON→クラスへの変換を行っています。

Earthquake.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
import "package:intl/intl.dart";

part 'earthquake.freezed.dart';
part 'earthquake.g.dart';


class Earthquake with _$Earthquake {
  const factory Earthquake({
    required String id,
    required int depth,
    required double latitude,
    required double longitude,
    required double magnitude,
    required String place,
    required int maxScale,
    () required DateTime time,
  }) = _Earthquake;

  factory Earthquake.fromJson(Map<String, Object?> json) =>
      _$EarthquakeFromJson(json);
}

class DateTimeConverter implements JsonConverter<DateTime, String> {
  const DateTimeConverter();

  
  DateTime fromJson(String json) {
    try {
      return DateTime.parse(json);
    } catch (e) {
      // 不正な形式の場合のエラーハンドリング
      print('Failed to parse DateTime: $json, Error: $e');
      throw FormatException('Invalid DateTime format', json);
    }
  }

  
  String toJson(DateTime object) {
    return object.toIso8601String();
  }
}

earthquake_sevice.dart
class EarthquakeData {
  static DateTime? firstDate;
  static DateTime? lastDate;
  static List<List<Earthquake>> earthquakes = [];
}

// 地震データを読み込み、EarthquakeDataへ保管
Future<void> loadJsonAsset() async {
  try {
       // jsonからデータ取得
    String contents =
        await rootBundle.loadString('assets/earthquake_data.json');
    var jsonData = json.decode(contents);
    var data = jsonData["data"];
    List<List<Earthquake>> monthGroupEarthquakes = [];

    // 年月でグループ化された地震情報を格納
    for (List earthquakesJson in data) {
      List<Earthquake> earthquakes = earthquakesJson.map((item) {
        Map<String, Object?> earthquakeJson = {
          "id": item["id"],
          "depth": item["earthquake"]["depth"],
          "latitude": item["earthquake"]["latitude"],
          "longitude": item["earthquake"]["longitude"],
          "magnitude": item["earthquake"]["magnitude"],
          "place": item["earthquake"]["name"],
          "maxScale": item["maxScale"],
          "time": item["time"],
        };
        return Earthquake.fromJson(earthquakeJson);
      }).toList();
      monthGroupEarthquakes.add(earthquakes);
    }
    // EarthquakeDataクラスに格納
    EarthquakeData.earthquakes = monthGroupEarthquakes;
    EarthquakeData.firstDate = DateTime.parse(jsonData["first_date"]);
    EarthquakeData.lastDate = DateTime.parse(jsonData["last_date"]);
  } catch (e) {
    print('Error loading JSON data: $e');
  }
}

便利なパッケージたち

flutter_screenutil
画面とフォントサイズを適応させるためのFlutterプラグイン。
どの画面サイズでも、同じレイアウトで表示されます。

https://pub.dev/packages/flutter_screenutil

flutter_map
Mapを表示します。デモ、ドキュメントが充実しており、おすすめ。

https://pub.dev/packages/flutter_map

Flutter学習中の所感

コード量多くないか?
Widgetをひたすら囲む特性上、改行が多くなり、逆に読みづらい気がする。。。

何かコツが必要なのかもしれない。

Discussion