├── example
├── ios
│ ├── Runner
│ │ ├── Runner-Bridging-Header.h
│ │ ├── Assets.xcassets
│ │ │ ├── LaunchImage.imageset
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ ├── README.md
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Base.lproj
│ │ │ ├── Main.storyboard
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ ├── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ ├── xcshareddata
│ │ │ └── xcschemes
│ │ │ │ └── Runner.xcscheme
│ │ └── project.pbxproj
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── Podfile.lock
│ ├── .gitignore
│ └── Podfile
├── android
│ ├── gradle.properties
│ ├── .gitignore
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── drawable
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ └── values
│ │ │ │ │ │ └── styles.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── settings.gradle
│ └── build.gradle
├── README.md
├── .gitignore
├── pubspec.yaml
├── pubspec.lock
├── lib
│ └── main.dart
└── assets
│ └── points.json
├── screens
├── 1.gif
├── 2.gif
├── 3.gif
└── 4.gif
├── assets
└── MapProjection.ttf
├── lib
├── simple_map.dart
└── src
│ ├── projections
│ ├── projection.dart
│ ├── miller_projection.dart
│ └── mercator_projection.dart
│ ├── utils.dart
│ ├── icon.dart
│ ├── animators
│ └── ray_point_animator.dart
│ ├── options.dart
│ ├── point.dart
│ ├── marker.dart
│ ├── map.dart
│ └── controller.dart
├── CHANGELOG.md
├── pubspec.yaml
├── .github
├── no-response.yml
├── workflows
│ └── ci.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.yml
│ └── bug_report.yml
├── test
├── simple_map_test.dart
└── controller_test.dart
├── .gitignore
├── analysis_options.yml
├── LICENSE
├── README.md
└── pubspec.lock
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/screens/1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/screens/1.gif
--------------------------------------------------------------------------------
/screens/2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/screens/2.gif
--------------------------------------------------------------------------------
/screens/3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/screens/3.gif
--------------------------------------------------------------------------------
/screens/4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/screens/4.gif
--------------------------------------------------------------------------------
/assets/MapProjection.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/assets/MapProjection.ttf
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiamo/flutter-simple-map/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/simple_map.dart:
--------------------------------------------------------------------------------
1 | library simple_map;
2 |
3 | export 'src/animators/ray_point_animator.dart';
4 | export 'src/controller.dart';
5 | export 'src/map.dart';
6 | export 'src/marker.dart';
7 | export 'src/options.dart';
8 | export 'src/point.dart';
9 |
--------------------------------------------------------------------------------
/lib/src/projections/projection.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | abstract class SimpleMapProjection {
4 | /// This method converts the [lat] and [lng] coordinates
5 | /// to map offset representation.
6 | Offset project(double? lat, double? lng, Size? size);
7 | }
8 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/src/utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/rendering.dart';
2 |
3 | class ColorHelper {
4 | static Color darken(Color color, [double amount = .1]) {
5 | assert(amount >= 0 && amount <= 1);
6 |
7 | final hsl = HSLColor.fromColor(color);
8 | final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
9 |
10 | return hslDark.toColor();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/lib/src/icon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | const _ff = 'MapProjection';
4 | const _fp = 'simple_map';
5 |
6 | ///
7 | /// Default map projection icons
8 | ///
9 | class MapProjectionIcon {
10 | const MapProjectionIcon._();
11 | static const miller = IconData(0xe900, fontFamily: _ff, fontPackage: _fp);
12 | static const mercator = IconData(0xe901, fontFamily: _ff, fontPackage: _fp);
13 | }
14 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.0.1] - 2022.08.12
2 |
3 | * Some refactory
4 |
5 | ## [1.0.0] - 2022.08.20
6 |
7 | * Custom point animation
8 | * Marker support
9 | * Zoom/Move map animation
10 | * Global improvements
11 | * Performance optimization
12 |
13 | ## [0.1.0] - 2020.07.11
14 |
15 | * Controller improved
16 | * Added tests
17 |
18 | ## [0.0.2] - 2020.07.10
19 |
20 | * Global code refactory
21 | * Added projection support
22 | * Example improved
23 | * Package renamed
24 |
25 | ## [0.0.1] - 2020.03.15
26 |
27 | * Basic implementation
28 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: simple_map
2 | description: A Flutter plugin for displaying a simple flat world map with animated points.
3 | version: 1.0.1
4 | homepage: 'https://github.com/tiamo/flutter-simple-map'
5 |
6 | environment:
7 | sdk: '>=2.12.0 <3.0.0'
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | dev_dependencies:
14 | flutter_test:
15 | sdk: flutter
16 | flutter_lints: ^2.0.0
17 | mockito: ^5.3.0
18 |
19 | flutter:
20 |
21 | fonts:
22 | - family: MapProjection
23 | fonts:
24 | - asset: assets/MapProjection.ttf
25 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - wakelock (0.0.1):
4 | - Flutter
5 |
6 | DEPENDENCIES:
7 | - Flutter (from `Flutter`)
8 | - wakelock (from `.symlinks/plugins/wakelock/ios`)
9 |
10 | EXTERNAL SOURCES:
11 | Flutter:
12 | :path: Flutter
13 | wakelock:
14 | :path: ".symlinks/plugins/wakelock/ios"
15 |
16 | SPEC CHECKSUMS:
17 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
18 | wakelock: 0d4a70faf8950410735e3f61fb15d517c8a6efc4
19 |
20 | PODFILE CHECKSUM: c34e2287a9ccaa606aeceab922830efb9a6ff69a
21 |
22 | COCOAPODS: 1.9.1
23 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Simple Map Example
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/.github/no-response.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-no-response - https://github.com/probot/no-response
2 |
3 | # Number of days of inactivity before an Issue is closed for lack of response
4 | daysUntilClose: 14
5 |
6 | # Label requiring a response
7 | responseRequiredLabel: "status: needs more info"
8 |
9 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable
10 | closeComment: >
11 | This issue has been automatically closed because there has been no response
12 | to our request for more information from the original author. With only the
13 | information that is currently in the issue, we don't have enough information
14 | to take action. Please reach out if you have or find the answers we need so
15 | that we can investigate further.
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches: [main]
7 | paths:
8 | - lib/**
9 | pull_request:
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 |
17 | - uses: actions/checkout@v3
18 |
19 | - uses: subosito/flutter-action@v2
20 | with:
21 | channel: 'beta' # 'dev', 'alpha', default to: 'stable'
22 | # flutter-version: '1.12.x' # you can also specify exact version of flutter
23 |
24 | - name: Download dependencies
25 | run: flutter pub get
26 |
27 | - name: Run Flutter Format
28 | run: flutter format --set-exit-if-changed lib
29 |
30 | - name: Run Flutter Analyzer
31 | run: flutter analyze
32 |
33 | - name: Run unit tests
34 | run: flutter test
35 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Exceptions to above rules.
40 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
41 |
--------------------------------------------------------------------------------
/test/simple_map_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_test/flutter_test.dart';
3 | import 'package:simple_map/simple_map.dart';
4 |
5 | void main() {
6 | SimpleMapOptions options = SimpleMapOptions();
7 | SimpleMapController controller = SimpleMapController(
8 | points: [
9 | SimpleMapPoint(lat: 0, lng: 0),
10 | ],
11 | );
12 |
13 | testWidgets('SimpleMap basic usage', (WidgetTester tester) async {
14 | final mapKey = Key('simple_map');
15 |
16 | // Build our app and trigger a frame.
17 | await tester.pumpWidget(
18 | MaterialApp(
19 | home: SimpleMap(
20 | key: mapKey,
21 | controller: controller,
22 | options: options,
23 | ),
24 | ),
25 | );
26 |
27 | expect(find.byKey(mapKey), findsOneWidget);
28 | });
29 | }
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
--------------------------------------------------------------------------------
/analysis_options.yml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 |
3 | linter:
4 | # The lint rules applied to this project can be customized in the
5 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
6 | # included above or to enable additional rules. A list of all available lints
7 | # and their documentation is published at
8 | # https://dart-lang.github.io/linter/lints/index.html.
9 | #
10 | # Instead of disabling a lint rule for the entire project in the
11 | # section below, it can also be suppressed for a single line of code
12 | # or a specific dart file by using the `// ignore: name_of_lint` and
13 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
14 | # producing the lint.
15 | rules:
16 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
17 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
18 |
19 | # Additional information about this file can be found at
20 | # https://dart.dev/guides/language/analysis-options
21 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Korniienko Vladyslav
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/lib/src/projections/miller_projection.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'dart:ui';
3 |
4 | import 'projection.dart';
5 |
6 | class MillerProjection implements SimpleMapProjection {
7 | const MillerProjection({
8 | this.mapWidth = 1080,
9 | this.mapHeight = 1080,
10 | this.offsetPrimeMeridian = -105,
11 | this.offsetEquator = 200,
12 | });
13 |
14 | final int mapWidth;
15 | final int mapHeight;
16 | final int offsetEquator;
17 | final int offsetPrimeMeridian;
18 |
19 | dynamic _toRadian(v) {
20 | return (v * pi) / 180;
21 | }
22 |
23 | @override
24 | Offset project(double? lat, double? lng, Size? size) {
25 | final scale = mapWidth / pi / 2;
26 | final ratio = size!.width / mapWidth;
27 |
28 | final double latRad = _toRadian(lat);
29 | final double lngRad = _toRadian(lng);
30 |
31 | var x = lngRad;
32 | var y = -1.25 * log(tan(pi / 4 + 0.4 * latRad));
33 |
34 | x *= scale;
35 | y *= scale;
36 |
37 | x += (mapWidth / 2) + offsetPrimeMeridian;
38 | y += (mapHeight / 2) + offsetEquator;
39 |
40 | x *= ratio;
41 | y *= ratio;
42 |
43 | return Offset(x, y);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Request a new feature
3 | title: "[Feature]: "
4 | labels: [enhancement]
5 | body:
6 | - type: textarea
7 | id: description
8 | attributes:
9 | label: Feature
10 | description: A clear and concise description of what the problem is, or what feature you want to be implemented.
11 | placeholder: I'm always frustrated when..., A good addition would be...
12 | validations:
13 | required: true
14 | - type: textarea
15 | id: solution
16 | attributes:
17 | label: Ideal solution or implementation
18 | description: A clear and concise description of what you want to happen.
19 | validations:
20 | required: true
21 | - type: textarea
22 | id: alternatives
23 | attributes:
24 | label: Alternative solutions or implementations
25 | description: A clear and concise description of any alternative solutions or features you have considered.
26 | - type: textarea
27 | id: additional-context
28 | attributes:
29 | label: Other context
30 | description: Any other context, screenshots, or file uploads that help us understand your feature request.
--------------------------------------------------------------------------------
/lib/src/projections/mercator_projection.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'dart:ui';
3 |
4 | import 'projection.dart';
5 |
6 | class MercatorProjection implements SimpleMapProjection {
7 | const MercatorProjection({
8 | this.mapWidth = 2048,
9 | this.mapHeight = 2048,
10 | this.longitudeLeft = -180,
11 | this.longitudeRight = 180,
12 | this.offsetEquator = 236,
13 | this.offsetPrimeMeridian = -62,
14 | });
15 |
16 | final int mapWidth;
17 | final int mapHeight;
18 | final int longitudeLeft;
19 | final int longitudeRight;
20 | final int offsetEquator;
21 | final int offsetPrimeMeridian;
22 |
23 | @override
24 | Offset project(double? lat, double? lng, Size? size) {
25 | final ratio = size!.width / mapWidth;
26 | final latRad = (lat! * pi) / 180;
27 |
28 | final g = log(tan(pi / 4 + latRad / 2));
29 | final lonOffset = longitudeRight - longitudeLeft;
30 |
31 | var dx = (lng! - longitudeLeft) * (mapWidth / lonOffset);
32 | var dy = mapHeight / 2 - (mapHeight * g) / (2 * pi);
33 |
34 | dx += offsetPrimeMeridian;
35 | dy += offsetEquator;
36 |
37 | dx *= ratio;
38 | dy *= ratio;
39 |
40 | return Offset(dx, dy);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/src/animators/ray_point_animator.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui' as ui;
2 |
3 | import 'package:flutter/widgets.dart';
4 | import 'package:simple_map/simple_map.dart';
5 |
6 | class RayMapPointAnimator implements SimpleMapPointAnimator {
7 | @override
8 | void render({
9 | required SimpleMapPoint point,
10 | required Animation animation,
11 | required Canvas canvas,
12 | required Offset center,
13 | }) {
14 | final height = Tween(
15 | begin: 0.0,
16 | end: 40.0,
17 | ).animate(
18 | CurvedAnimation(
19 | parent: animation,
20 | curve: const Interval(0.0, 1.0, curve: Cubic(0.02, 2.0, 0.04, 1.0)),
21 | ),
22 | );
23 |
24 | final r = Rect.fromCenter(
25 | center: Offset(center.dx, center.dy - height.value / 2),
26 | width: point.targetRadius,
27 | height: height.value,
28 | );
29 |
30 | final color = point.targetColor ?? point.color ?? Color(0x0);
31 |
32 | canvas.drawRect(
33 | r,
34 | Paint()
35 | ..shader = ui.Gradient.linear(
36 | r.topCenter,
37 | r.bottomCenter,
38 | [
39 | color.withAlpha(0),
40 | color,
41 | ],
42 | ),
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug report
2 | title: "[Bug]: "
3 | description: Report incorrect or unexpected behavior
4 | labels: [bug]
5 | body:
6 | - type: textarea
7 | id: description
8 | attributes:
9 | label: Issue description
10 | description: |
11 | Describe the issue in as much detail as possible.
12 |
13 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files into it.
14 | placeholder: |
15 | Steps to reproduce with:
16 | 1. do thing
17 | 2. observe behavior
18 | 3. see error logs below
19 | validations:
20 | required: true
21 | - type: textarea
22 | id: logs
23 | attributes:
24 | label: Relevant log output
25 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
26 | render: shell
27 | validations:
28 | required: false
29 | - type: dropdown
30 | id: priority
31 | attributes:
32 | label: Priority this issue should have
33 | description: Please be realistic. If you need to elaborate on your reasoning, please use the Issue description field above.
34 | options:
35 | - Low (slightly annoying)
36 | - Medium (should be fixed soon)
37 | - High (immediate attention needed)
38 | validations:
39 | required: true
--------------------------------------------------------------------------------
/lib/src/options.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | import 'icon.dart';
4 | import 'marker.dart';
5 | import 'projections/miller_projection.dart';
6 | import 'projections/projection.dart';
7 |
8 | class SimpleMapOptions {
9 | const SimpleMapOptions({
10 | this.interactive = true,
11 | this.projection = const MillerProjection(
12 | offsetEquator: 77,
13 | offsetPrimeMeridian: -33,
14 | ),
15 | this.mapIcon = MapProjectionIcon.miller,
16 | this.mapColor = const Color(0xFFCDD0D7),
17 | this.bgColor = const Color(0x0),
18 | this.pointColor,
19 | this.startPointColor,
20 | this.withShadow = true,
21 | this.shadowOffset = const Offset(0.0, 0.5),
22 | this.markerBuilder,
23 | });
24 |
25 | /// Map projection
26 | final SimpleMapProjection projection;
27 |
28 | /// Map's vector representation based on [IconData]
29 | final IconData mapIcon;
30 |
31 | /// The color of the map
32 | final Color mapColor;
33 |
34 | /// The color of the map canvas
35 | final Color bgColor;
36 |
37 | /// The color of the map's point
38 | final Color? pointColor;
39 |
40 | /// The start color of the map's point animation
41 | final Color? startPointColor;
42 |
43 | /// Marker builder
44 | final Widget Function(SimpleMapMarker, Offset)? markerBuilder;
45 |
46 | /// 3D effect (based on map shadow)
47 | final bool withShadow;
48 |
49 | /// The map's shadow offset
50 | final Offset shadowOffset;
51 |
52 | /// Enable map animation
53 | final bool interactive;
54 | }
55 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | example
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/test/controller_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter_test/flutter_test.dart';
3 | import 'package:mockito/mockito.dart';
4 | import 'package:simple_map/simple_map.dart';
5 |
6 | class MockCanvas extends Mock implements Canvas {
7 | @override
8 | void drawCircle(Offset? c, double? radius, Paint? paint) {
9 | super.noSuchMethod(Invocation.method(#drawCircle, [c, radius, paint]));
10 | }
11 | }
12 |
13 | void main() {
14 | final animation = AnimationController(
15 | duration: const Duration(milliseconds: 100),
16 | vsync: const TestVSync(),
17 | );
18 |
19 | final options = SimpleMapOptions();
20 |
21 | test('test addPoint & clear', () {
22 | final controller = SimpleMapController();
23 | controller.addPoint(SimpleMapPoint(lat: 0, lng: 0));
24 |
25 | expect(controller.points?.length, 1);
26 |
27 | controller.clear();
28 |
29 | expect(controller.points?.length, 0);
30 | });
31 |
32 | test('test render', () async {
33 | final controller = SimpleMapController(
34 | points: [
35 | SimpleMapPoint(
36 | lat: 0,
37 | lng: 0,
38 | color: Color(0xFFFFFFFF),
39 | )
40 | ],
41 | );
42 |
43 | final canvas = MockCanvas();
44 | final size = Size.square(100);
45 |
46 | controller.configure(
47 | options: options,
48 | animation: animation,
49 | );
50 |
51 | controller.render(canvas, size);
52 | verify(canvas.drawCircle(any, any, any)).called(2);
53 |
54 | controller.addPoint(
55 | SimpleMapPoint(
56 | lat: 0,
57 | lng: 0,
58 | color: Color(0xFFFFFFFF),
59 | state: SimpleMapPointState.active,
60 | ),
61 | );
62 |
63 | controller.render(canvas, size);
64 | verify(canvas.drawCircle(any, any, any)).called(3);
65 | });
66 | }
67 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 28
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "com.example.example"
42 | minSdkVersion 16
43 | targetSdkVersion 28
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | }
47 |
48 | buildTypes {
49 | release {
50 | // TODO: Add your own signing config for the release build.
51 | // Signing with the debug keys for now, so `flutter run --release` works.
52 | signingConfig signingConfigs.debug
53 | }
54 | }
55 | }
56 |
57 | flutter {
58 | source '../..'
59 | }
60 |
61 | dependencies {
62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
63 | }
64 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 |
4 | version: 1.0.0+1
5 |
6 | publish_to: none
7 |
8 | environment:
9 | sdk: ">=2.1.0 <3.0.0"
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 |
15 | wakelock: ^0.1.3+4
16 |
17 | simple_map:
18 | path: ../
19 |
20 | # The following adds the Cupertino Icons font to your application.
21 | # Use with the CupertinoIcons class for iOS style icons.
22 | cupertino_icons: ^0.1.3
23 |
24 | dev_dependencies:
25 | flutter_test:
26 | sdk: flutter
27 |
28 | # For information on the generic Dart part of this file, see the
29 | # following page: https://dart.dev/tools/pub/pubspec
30 |
31 | # The following section is specific to Flutter.
32 | flutter:
33 |
34 | # The following line ensures that the Material Icons font is
35 | # included with your application, so that you can use the icons in
36 | # the material Icons class.
37 | uses-material-design: true
38 |
39 | # To add assets to your application, add an assets section, like this:
40 | assets:
41 | - assets/
42 |
43 | # An image asset can refer to one or more resolution-specific "variants", see
44 | # https://flutter.dev/assets-and-images/#resolution-aware.
45 |
46 | # For details regarding adding assets from package dependencies, see
47 | # https://flutter.dev/assets-and-images/#from-packages
48 |
49 | # To add custom fonts to your application, add a fonts section here,
50 | # in this "flutter" section. Each entry in this list should have a
51 | # "family" key with the font family name, and a "fonts" key with a
52 | # list giving the asset and other descriptors for the font. For
53 | # example:
54 | # fonts:
55 | # - family: Schyler
56 | # fonts:
57 | # - asset: fonts/Schyler-Regular.ttf
58 | # - asset: fonts/Schyler-Italic.ttf
59 | # style: italic
60 | # - family: Trajan Pro
61 | # fonts:
62 | # - asset: fonts/TrajanPro.ttf
63 | # - asset: fonts/TrajanPro_Bold.ttf
64 | # weight: 700
65 | #
66 | # For details regarding fonts from package dependencies,
67 | # see https://flutter.dev/custom-fonts/#from-packages
68 |
--------------------------------------------------------------------------------
/lib/src/point.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | enum SimpleMapPointState {
4 | idle,
5 | showing,
6 | hiding,
7 | active,
8 | inactive,
9 | }
10 |
11 | class SimpleMapPoint {
12 | SimpleMapPoint({
13 | this.lat = 0.0,
14 | this.lng = 0.0,
15 | this.radius = 1.0,
16 | this.opacity = 1.0,
17 | this.color,
18 | this.ttl = Duration.zero,
19 | this.state = SimpleMapPointState.idle,
20 | this.fractionDigits = 1,
21 | this.animator,
22 | });
23 |
24 | /// Point `latitude` coordinate
25 | final double lat;
26 |
27 | /// Point `longitude` coordinate
28 | final double lng;
29 |
30 | /// Point radius
31 | double radius;
32 |
33 | /// Point radius used in animation
34 | double targetRadius = 1.0;
35 |
36 | /// Point opacity
37 | double opacity;
38 |
39 | /// Point color
40 | Color? color;
41 |
42 | /// Point color used in animation
43 | Color? targetColor;
44 |
45 | /// Point time to live [Duration]
46 | Duration? ttl;
47 |
48 | /// Point state
49 | SimpleMapPointState state;
50 |
51 | /// Point showing effect animator
52 | final SimpleMapPointAnimator? animator;
53 |
54 | /// Optimize render for a large number of points.
55 | final int fractionDigits;
56 |
57 | @override
58 | String toString() {
59 | return '$runtimeType {state: $state, lat: $lat, lng: $lng, radius: $radius, targetRadius: $targetRadius, color: $color, ttl: $ttl}';
60 | }
61 |
62 | @override
63 | bool operator ==(Object other) {
64 | if (identical(this, other)) {
65 | return true;
66 | }
67 | return other is SimpleMapPoint &&
68 | lat.toStringAsFixed(fractionDigits) ==
69 | other.lat.toStringAsFixed(fractionDigits) &&
70 | lng.toStringAsFixed(fractionDigits) ==
71 | other.lng.toStringAsFixed(fractionDigits);
72 | }
73 |
74 | @override
75 | int get hashCode {
76 | return lat.toStringAsFixed(fractionDigits).hashCode ^
77 | lng.toStringAsFixed(fractionDigits).hashCode ^
78 | radius.hashCode;
79 | }
80 | }
81 |
82 | ///
83 | /// Point render animator used in animation
84 | ///
85 | abstract class SimpleMapPointAnimator {
86 | void render({
87 | required SimpleMapPoint point,
88 | required Animation animation,
89 | required Canvas canvas,
90 | required Offset center,
91 | });
92 | }
93 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
23 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🗺️ Flutter Simple Map
2 |
3 | A Flutter plugin, which displays a simple flat world map with animated dots, useful for real time data representation.
4 | Can be used as a presentation of online users, devices, etc.
5 |
6 | [](https://github.com/tiamo/flutter-simple-map)
7 | [](https://pub.dartlang.org/packages/simple_map)
8 | [](https://github.com/tiamo/flutter-simple-map)
9 | [](https://opensource.org/licenses/MIT)
10 |
11 | 


12 |
13 | ## Getting Started
14 |
15 | * Add this to your pubspec.yaml
16 | ```
17 | dependencies:
18 | simple_map: ^1.0.0
19 | ```
20 | * Get the package from Pub:
21 | ```
22 | flutter packages get
23 | ```
24 | * Import it in your file
25 | ```
26 | import 'package:simple_map/simple_map.dart';
27 | ```
28 |
29 | ## Features
30 |
31 | * 🚀 Good performance with lot of data
32 | * 🌎 Render simple customizable flat map
33 | * 🪄 Render points with animation effect
34 | * ✨ Customize every point
35 | * ⏱️ Create points with TTL
36 | * 📍 Marker support
37 | * 🔍 Zoom and Move animations
38 |
39 | ## Usage
40 |
41 | * Using SimpleMapOptions
42 | ```dart
43 | final mapOptions = SimpleMapOptions(
44 | // Custom map icon with projection
45 | // mapIcon: IconData(0xe900, fontFamily: 'MapIcons'),
46 | // projection: ...
47 |
48 | mapColor: Colors.grey,
49 | bgColor: Colors.black,
50 | // Default point color
51 | pointColor: Colors.blue,
52 |
53 | interactive: true,
54 |
55 | // 3d effect
56 | withShadow: true,
57 | shadowOffset = const Offset(0.0, 0.5),
58 | );
59 | ```
60 |
61 | * Using SimpleMapController
62 | ```dart
63 | final SimpleMapController mapController = SimpleMapController();
64 |
65 | // Add single point.
66 | mapController.addPoint(SimpleMapPoint());
67 |
68 | // Add list of points
69 | mapController.points = [SimpleMapPoint()];
70 |
71 | // Clear the map.
72 | mapController.clear();
73 |
74 | SimpleMap(
75 | controller: mapController,
76 | options: mapOptions,
77 | ),
78 | ```
79 |
80 | * Simple map with one center point with duration of 100 seconds
81 | ```dart
82 | SimpleMap(
83 | controller: SimpleMapController(points: [
84 | SimpleMapPoint(
85 | lat: 0.0,
86 | lng: 0.0,
87 | color: Colors.blue,
88 | ttl: Duration(seconds: 100),
89 | )
90 | ]),
91 | options: mapOptions,
92 | ),
93 | ```
94 |
95 | Check out the complete [Example](https://github.com/tiamo/flutter-simple-map/tree/master/example)
96 |
97 | ## Changelog
98 |
99 | Please have a look in [CHANGELOG](CHANGELOG.md)
100 |
101 | ## Maintainers
102 |
103 | * [Vlad Korniienko](https://github.com/tiamo)
104 |
105 | ## License
106 |
107 | [](https://opensource.org/licenses/MIT)
108 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | generated_key_values = {}
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) do |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | generated_key_values[podname] = podpath
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | end
32 | generated_key_values
33 | end
34 |
35 | target 'Runner' do
36 | use_frameworks!
37 | use_modular_headers!
38 |
39 | # Flutter Pod
40 |
41 | copied_flutter_dir = File.join(__dir__, 'Flutter')
42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
48 |
49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
50 | unless File.exist?(generated_xcode_build_settings_path)
51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
52 | end
53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
55 |
56 | unless File.exist?(copied_framework_path)
57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
58 | end
59 | unless File.exist?(copied_podspec_path)
60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
61 | end
62 | end
63 |
64 | # Keep pod path relative so it can be checked into Podfile.lock.
65 | pod 'Flutter', :path => 'Flutter'
66 |
67 | # Plugin Pods
68 |
69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
70 | # referring to absolute paths on developers' machines.
71 | system('rm -rf .symlinks')
72 | system('mkdir -p .symlinks/plugins')
73 | plugin_pods = parse_KV_file('../.flutter-plugins')
74 | plugin_pods.each do |name, path|
75 | symlink = File.join('.symlinks', 'plugins', name)
76 | File.symlink(path, symlink)
77 | pod name, :path => File.join(symlink, 'ios')
78 | end
79 | end
80 |
81 | post_install do |installer|
82 | installer.pods_project.targets.each do |target|
83 | target.build_configurations.each do |config|
84 | config.build_settings['ENABLE_BITCODE'] = 'NO'
85 | end
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/lib/src/marker.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 |
3 | const _kColorWhite = const Color(0xFFFFFFFF);
4 |
5 | class SimpleMapMarker {
6 | const SimpleMapMarker({
7 | this.lat = 0.0,
8 | this.lng = 0.0,
9 | this.radius = 10.0,
10 | this.color = _kColorWhite,
11 | this.image,
12 | });
13 |
14 | /// Latitude
15 | final double lat;
16 |
17 | /// Longitude
18 | final double lng;
19 |
20 | /// Marker radius
21 | final double radius;
22 |
23 | /// Marker color
24 | final Color color;
25 |
26 | /// Marker image
27 | final ImageProvider? image;
28 |
29 | @override
30 | String toString() {
31 | return '$runtimeType {radius: $radius, lat: $lat, lng: $lng, radius: $radius, color: $color}';
32 | }
33 | }
34 |
35 | class SimpleMarkerPainter extends CustomPainter {
36 | const SimpleMarkerPainter({
37 | this.color = _kColorWhite,
38 | });
39 |
40 | /// Marker background color
41 | final Color color;
42 |
43 | @override
44 | void paint(Canvas canvas, Size size) {
45 | final path = Path()
46 | ..moveTo(size.width * 1.000004, size.height * 0.4109621)
47 | ..cubicTo(
48 | size.width * 1.000004,
49 | size.height * 0.1865600,
50 | size.width * 0.7801875,
51 | size.height * 0.004645000,
52 | size.width * 0.5090333,
53 | size.height * 0.004645000)
54 | ..cubicTo(
55 | size.width * 0.2378804,
56 | size.height * 0.004645000,
57 | size.width * 0.01806642,
58 | size.height * 0.1865600,
59 | size.width * 0.01806642,
60 | size.height * 0.4109621)
61 | ..cubicTo(
62 | size.width * 0.01806642,
63 | size.height * 0.6574069,
64 | size.width * 0.3166987,
65 | size.height * 0.8147586,
66 | size.width * 0.5090333,
67 | size.height * 0.9723000)
68 | ..cubicTo(
69 | size.width * 0.7013667,
70 | size.height * 0.8147586,
71 | size.width * 1.000004,
72 | size.height * 0.6574069,
73 | size.width * 1.000004,
74 | size.height * 0.4109621)
75 | ..close();
76 |
77 | final paint = Paint()
78 | ..style = PaintingStyle.fill
79 | ..color = color;
80 |
81 | canvas.drawPath(path, paint);
82 | }
83 |
84 | @override
85 | bool shouldRepaint(covariant CustomPainter oldDelegate) {
86 | return true;
87 | }
88 | }
89 |
90 | Widget defaultMarkerBuilder(SimpleMapMarker m, Offset offset) {
91 | const border = 1.4;
92 | final width = m.radius * 2;
93 | final size = Size(width, width * 1.21);
94 | return Positioned(
95 | top: offset.dy - size.height + 0.6,
96 | left: offset.dx - m.radius - 0.2,
97 | child: Stack(
98 | clipBehavior: Clip.none,
99 | alignment: Alignment.topCenter,
100 | children: [
101 | CustomPaint(
102 | painter: SimpleMarkerPainter(color: m.color),
103 | size: size,
104 | ),
105 | Container(
106 | width: size.width - border * 2,
107 | height: size.width - border * 2,
108 | margin: const EdgeInsets.only(top: border),
109 | decoration: BoxDecoration(
110 | image: m.image != null
111 | ? DecorationImage(image: m.image!, fit: BoxFit.cover)
112 | : null,
113 | shape: BoxShape.circle,
114 | color: _kColorWhite.withOpacity(0.7),
115 | ),
116 | )
117 | ],
118 | ),
119 | );
120 | }
121 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.9.0"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.1.0"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.2.1"
25 | clock:
26 | dependency: transitive
27 | description:
28 | name: clock
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.1.0"
32 | collection:
33 | dependency: transitive
34 | description:
35 | name: collection
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.16.0"
39 | cupertino_icons:
40 | dependency: "direct main"
41 | description:
42 | name: cupertino_icons
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "0.1.3"
46 | fake_async:
47 | dependency: transitive
48 | description:
49 | name: fake_async
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.3.0"
53 | flutter:
54 | dependency: "direct main"
55 | description: flutter
56 | source: sdk
57 | version: "0.0.0"
58 | flutter_test:
59 | dependency: "direct dev"
60 | description: flutter
61 | source: sdk
62 | version: "0.0.0"
63 | matcher:
64 | dependency: transitive
65 | description:
66 | name: matcher
67 | url: "https://pub.dartlang.org"
68 | source: hosted
69 | version: "0.12.11"
70 | material_color_utilities:
71 | dependency: transitive
72 | description:
73 | name: material_color_utilities
74 | url: "https://pub.dartlang.org"
75 | source: hosted
76 | version: "0.1.5"
77 | meta:
78 | dependency: transitive
79 | description:
80 | name: meta
81 | url: "https://pub.dartlang.org"
82 | source: hosted
83 | version: "1.8.0"
84 | path:
85 | dependency: transitive
86 | description:
87 | name: path
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "1.8.2"
91 | simple_map:
92 | dependency: "direct main"
93 | description:
94 | path: ".."
95 | relative: true
96 | source: path
97 | version: "1.0.0"
98 | sky_engine:
99 | dependency: transitive
100 | description: flutter
101 | source: sdk
102 | version: "0.0.99"
103 | source_span:
104 | dependency: transitive
105 | description:
106 | name: source_span
107 | url: "https://pub.dartlang.org"
108 | source: hosted
109 | version: "1.9.0"
110 | stack_trace:
111 | dependency: transitive
112 | description:
113 | name: stack_trace
114 | url: "https://pub.dartlang.org"
115 | source: hosted
116 | version: "1.10.0"
117 | stream_channel:
118 | dependency: transitive
119 | description:
120 | name: stream_channel
121 | url: "https://pub.dartlang.org"
122 | source: hosted
123 | version: "2.1.0"
124 | string_scanner:
125 | dependency: transitive
126 | description:
127 | name: string_scanner
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "1.1.1"
131 | term_glyph:
132 | dependency: transitive
133 | description:
134 | name: term_glyph
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "1.2.0"
138 | test_api:
139 | dependency: transitive
140 | description:
141 | name: test_api
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "0.4.9"
145 | vector_math:
146 | dependency: transitive
147 | description:
148 | name: vector_math
149 | url: "https://pub.dartlang.org"
150 | source: hosted
151 | version: "2.1.2"
152 | wakelock:
153 | dependency: "direct main"
154 | description:
155 | name: wakelock
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "0.1.4+2"
159 | sdks:
160 | dart: ">=2.17.0-0 <3.0.0"
161 | flutter: ">=1.12.0"
162 |
--------------------------------------------------------------------------------
/lib/src/map.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | // import 'package:shimmer/shimmer.dart';
4 |
5 | import 'controller.dart';
6 | import 'marker.dart';
7 | import 'options.dart';
8 | import 'utils.dart';
9 |
10 | const _kDefaultDuration = Duration(seconds: 1);
11 |
12 | class SimpleMap extends StatefulWidget {
13 | const SimpleMap({
14 | Key? key,
15 | required this.options,
16 | required this.controller,
17 | }) : super(key: key);
18 |
19 | /// [SimpleMap] options
20 | final SimpleMapOptions options;
21 |
22 | /// [SimpleMap] controller
23 | final SimpleMapController controller;
24 |
25 | @override
26 | _SimpleMapState createState() => _SimpleMapState();
27 | }
28 |
29 | class _SimpleMapState extends State
30 | with TickerProviderStateMixin, WidgetsBindingObserver {
31 | AnimationController? _pointAnimation;
32 | AnimationController? _transformAnimation;
33 |
34 | Widget? _mapIcon;
35 | double? _size;
36 |
37 | @override
38 | void initState() {
39 | if (widget.options.interactive) {
40 | _pointAnimation = AnimationController(
41 | vsync: this,
42 | duration: _kDefaultDuration,
43 | debugLabel: 'SimpleMap.points',
44 | );
45 | _pointAnimation!.repeat();
46 | }
47 |
48 | _transformAnimation = AnimationController(
49 | vsync: this,
50 | debugLabel: 'SimpleMap.transform',
51 | );
52 |
53 | widget.controller.configure(
54 | state: this,
55 | options: widget.options,
56 | animation: _pointAnimation,
57 | transformAnimation: _transformAnimation,
58 | );
59 |
60 | super.initState();
61 |
62 | WidgetsBinding.instance.addObserver(this);
63 | }
64 |
65 | @override
66 | void dispose() {
67 | _pointAnimation?.dispose();
68 | _transformAnimation?.dispose();
69 | super.dispose();
70 |
71 | WidgetsBinding.instance.removeObserver(this);
72 | }
73 |
74 | @override
75 | void didChangeAppLifecycleState(AppLifecycleState state) {
76 | switch (state) {
77 | case AppLifecycleState.resumed:
78 | widget.controller.startAnimation();
79 | break;
80 | case AppLifecycleState.paused:
81 | widget.controller.stopAnimation();
82 | break;
83 | case AppLifecycleState.inactive:
84 | break;
85 | case AppLifecycleState.detached:
86 | break;
87 | }
88 | }
89 |
90 | @override
91 | Widget build(BuildContext context) {
92 | return LayoutBuilder(
93 | builder: (context, constraints) {
94 | if (_size != constraints.maxWidth) {
95 | _size = constraints.maxWidth;
96 | _mapIcon ??= _buildMap(constraints.maxWidth);
97 | widget.controller.size = Size.square(constraints.maxWidth);
98 | }
99 |
100 | Widget mapIcon = _mapIcon!;
101 |
102 | // if (widget.controller.isBusy) {
103 | // mapIcon = Shimmer.fromColors(
104 | // baseColor: widget.options.mapColor,
105 | // highlightColor: ColorHelper.lighten(widget.options.mapColor, 0.2),
106 | // enabled: true,
107 | // child: _mapIcon,
108 | // );
109 | // }
110 |
111 | // mapIcon = Offstage(offstage: true, child: mapIcon);
112 |
113 | Widget map = FittedBox(
114 | alignment: Alignment.center,
115 | fit: BoxFit.fitWidth,
116 | child: Stack(
117 | clipBehavior: Clip.none,
118 | fit: StackFit.loose,
119 | children: [
120 | CustomPaint(
121 | foregroundPainter: _SimpleMapPainter(
122 | widget.controller,
123 | _pointAnimation,
124 | ),
125 | child: mapIcon,
126 | ),
127 | ..._buildMarkers()
128 | ],
129 | ),
130 | );
131 |
132 | if (_transformAnimation != null) {
133 | map = AnimatedBuilder(
134 | animation: _transformAnimation!,
135 | builder: (ctx, map) {
136 | return Transform.scale(
137 | scale: widget.controller.zoom,
138 | child: FractionalTranslation(
139 | translation: widget.controller.translation,
140 | child: map,
141 | ),
142 | );
143 | },
144 | child: map,
145 | );
146 | }
147 |
148 | return ColoredBox(
149 | color: widget.options.bgColor,
150 | child: map,
151 | );
152 | },
153 | );
154 | }
155 |
156 | Widget _buildMap(double size) {
157 | return SizedBox.square(
158 | dimension: size,
159 | child: Center(
160 | child: RichText(
161 | overflow: TextOverflow.visible,
162 | text: TextSpan(
163 | text: String.fromCharCode(widget.options.mapIcon.codePoint),
164 | style: TextStyle(
165 | inherit: false,
166 | color: widget.options.mapColor,
167 | fontSize: size / 2,
168 | height: 1.0,
169 | fontFamily: widget.options.mapIcon.fontFamily,
170 | package: widget.options.mapIcon.fontPackage,
171 | shadows: widget.options.withShadow
172 | ? [
173 | Shadow(
174 | color: ColorHelper.darken(
175 | widget.options.mapColor,
176 | 0.12,
177 | ),
178 | offset: widget.options.shadowOffset,
179 | ),
180 | ]
181 | : null,
182 | ),
183 | ),
184 | ),
185 | ),
186 | );
187 | }
188 |
189 | List _buildMarkers() {
190 | return widget.controller.markers.map((m) {
191 | final offset = widget.controller.project(m.lat, m.lng);
192 | return widget.options.markerBuilder != null
193 | ? widget.options.markerBuilder!(m, offset)
194 | : defaultMarkerBuilder(m, offset);
195 | }).toList();
196 | }
197 | }
198 |
199 | class _SimpleMapPainter extends CustomPainter {
200 | const _SimpleMapPainter(
201 | this.controller,
202 | this.animation,
203 | ) : super(repaint: animation);
204 |
205 | /// Painter animation
206 | final Animation? animation;
207 |
208 | /// [SimpleMap] controller
209 | final SimpleMapController controller;
210 |
211 | @override
212 | void paint(Canvas canvas, Size size) => controller.render(canvas, size);
213 |
214 | @override
215 | bool shouldRepaint(_SimpleMapPainter oldDelegate) =>
216 | true; // !identical(this, oldDelegate);
217 | }
218 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 | import 'dart:math';
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/scheduler.dart';
6 | import 'package:flutter/services.dart';
7 | import 'package:simple_map/simple_map.dart';
8 | import 'package:wakelock/wakelock.dart';
9 |
10 | void main() {
11 | runApp(MyApp());
12 | Wakelock.enable();
13 | }
14 |
15 | class MyApp extends StatelessWidget {
16 | @override
17 | Widget build(BuildContext context) {
18 | return MaterialApp(
19 | title: 'Flutter Simple Map Demo',
20 | debugShowCheckedModeBanner: false,
21 | theme: ThemeData(
22 | primarySwatch: Colors.blue,
23 | ),
24 | home: MyHomePage(),
25 | );
26 | }
27 | }
28 |
29 | class MyHomePage extends StatefulWidget {
30 | MyHomePage({Key key, this.title}) : super(key: key);
31 |
32 | final String title;
33 |
34 | @override
35 | _MyHomePageState createState() => _MyHomePageState();
36 | }
37 |
38 | class _MyHomePageState extends State
39 | with SingleTickerProviderStateMixin {
40 | static Random random = Random();
41 |
42 | SimpleMapOptions _mapOptions;
43 | SimpleMapController _mapController;
44 |
45 | Ticker _ticker;
46 |
47 | List _points = [];
48 |
49 | @override
50 | void initState() {
51 | _mapOptions = SimpleMapOptions(
52 | pointColor: Colors.blue,
53 | );
54 | _mapController = SimpleMapController();
55 | initRealtimeTicker();
56 |
57 | loadPoints().then((points) {
58 | _points = points;
59 | generateRandomPoints(1000);
60 | });
61 |
62 | super.initState();
63 | }
64 |
65 | void initRealtimeTicker() {
66 | _ticker = createTicker((elapsed) {
67 | final sec = elapsed.inSeconds;
68 | if (sec > 3) {
69 | final randMod = random.nextInt(100);
70 | if (randMod == 0) return;
71 | if (sec % randMod == 0) {
72 | final points = generatePoints(
73 | random.nextInt(3),
74 | color: Colors.primaries[random.nextInt(Colors.primaries.length)],
75 | );
76 | if (points.length > 0) {
77 | debugPrint('Point {ttl: ${points.first.ttl}}');
78 | _mapController.points = points;
79 | }
80 | }
81 | }
82 | });
83 | }
84 |
85 | Future loadPoints() async {
86 | String points = await rootBundle.loadString('assets/points.json');
87 | return json.decode(points);
88 | }
89 |
90 | @override
91 | void dispose() {
92 | _ticker?.dispose();
93 | super.dispose();
94 | }
95 |
96 | void generateRandomPoints(int num) {
97 | assert(_mapController != null);
98 | final List points = generatePoints(random.nextInt(num));
99 |
100 | _mapController.points = points;
101 | }
102 |
103 | List generatePoints(
104 | int num, {
105 | int maxTTL = 120,
106 | Color color = Colors.blue,
107 | }) {
108 | if (num <= 0 || _points.length == 0) {
109 | return [];
110 | }
111 | return List.generate(num, (index) {
112 | var p = _points[random.nextInt(_points.length)];
113 | return SimpleMapPoint(
114 | lat: double.tryParse(p[0]),
115 | lng: double.tryParse(p[1]),
116 | color: color,
117 | ttl: Duration(seconds: random.nextInt(maxTTL) + 5),
118 | animator: random.nextInt(3) == 1 ? RayMapPointAnimator() : null,
119 | );
120 | });
121 | }
122 |
123 | bool liveEnabled = false;
124 |
125 | @override
126 | Widget build(BuildContext context) {
127 | return Scaffold(
128 | appBar: AppBar(
129 | title: Text('Simple Map Demo'),
130 | ),
131 | backgroundColor: Color(0xffff9f9f9),
132 | body: Center(
133 | child: Column(
134 | mainAxisAlignment: MainAxisAlignment.center,
135 | children: [
136 | Padding(
137 | padding: const EdgeInsets.symmetric(horizontal: 20),
138 | child: SimpleMap(
139 | controller: _mapController,
140 | options: _mapOptions,
141 | ),
142 | ),
143 | ],
144 | ),
145 | ),
146 | persistentFooterButtons: [
147 | Text("Realtime data"),
148 | Switch(
149 | value: liveEnabled,
150 | onChanged: (value) {
151 | if (value) {
152 | _ticker.start();
153 | } else {
154 | _ticker.stop();
155 | }
156 | setState(() {
157 | liveEnabled = value;
158 | });
159 | },
160 | ),
161 | ],
162 | floatingActionButton: Wrap(
163 | spacing: 10,
164 | children: [
165 | FloatingActionButton(
166 | onPressed: () {
167 | generateRandomPoints(random.nextInt(10) + 1);
168 | },
169 | tooltip: 'Add random points',
170 | child: Icon(Icons.add_circle),
171 | ),
172 | FloatingActionButton(
173 | onPressed: () {
174 | _mapController.flyTo(0, 0, zoom: 5.0);
175 | },
176 | tooltip: 'Zoom In',
177 | child: Icon(Icons.zoom_in),
178 | ),
179 | FloatingActionButton(
180 | onPressed: () {
181 | final point = generatePoints(1)[0];
182 | _mapController.addMarker(
183 | SimpleMapMarker(
184 | lat: point.lat,
185 | lng: point.lng,
186 | color:
187 | Colors.primaries[random.nextInt(Colors.primaries.length)],
188 | image: NetworkImage(
189 | 'https://avatars.githubusercontent.com/u/1963342?s=50',
190 | // 'https://avatars.githubusercontent.com/u/14101776?s=50',
191 | ),
192 | ),
193 | );
194 | },
195 | tooltip: 'Add marker',
196 | child: Icon(Icons.add_card),
197 | backgroundColor: Colors.deepOrangeAccent,
198 | ),
199 | ],
200 | ),
201 | );
202 | }
203 |
204 | // void fakeData() {
205 | // assert(_map != null);
206 | // final List points = []; // generatePoints(random.nextInt(1000));
207 | //
208 | // points.add(OWMapPoint(
209 | // lat: 0.0,
210 | // lng: 0.0,
211 | // radius: 2.0,
212 | // color: Colors.black,
213 | // ttl: Duration(hours: 1),
214 | // fractionDigits: 5,
215 | // ));
216 | //
217 | // _map.points = points;
218 | // _animation.addListener(() {
219 | // final sec = _animation.lastElapsedDuration.inSeconds;
220 | // if (sec > 3) {
221 | // final randMod = random.nextInt(100);
222 | // if (randMod == 0) return;
223 | // if (sec % randMod == 0) {
224 | // final points = generatePoints(random.nextInt(3));
225 | // if (points.length > 0) {
226 | // debugPrint('Point {ttl: ${points.first.ttl}}');
227 | // _map.points = points;
228 | // }
229 | // }
230 | // }
231 | // });
232 | // }
233 |
234 | }
235 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | _fe_analyzer_shared:
5 | dependency: transitive
6 | description:
7 | name: _fe_analyzer_shared
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "46.0.0"
11 | analyzer:
12 | dependency: transitive
13 | description:
14 | name: analyzer
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "4.6.0"
18 | args:
19 | dependency: transitive
20 | description:
21 | name: args
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.5.2"
25 | async:
26 | dependency: transitive
27 | description:
28 | name: async
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "2.9.0"
32 | boolean_selector:
33 | dependency: transitive
34 | description:
35 | name: boolean_selector
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "2.1.0"
39 | build:
40 | dependency: transitive
41 | description:
42 | name: build
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "2.3.0"
46 | built_collection:
47 | dependency: transitive
48 | description:
49 | name: built_collection
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "5.1.1"
53 | built_value:
54 | dependency: transitive
55 | description:
56 | name: built_value
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "8.4.1"
60 | characters:
61 | dependency: transitive
62 | description:
63 | name: characters
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "1.2.1"
67 | clock:
68 | dependency: transitive
69 | description:
70 | name: clock
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "1.1.0"
74 | code_builder:
75 | dependency: transitive
76 | description:
77 | name: code_builder
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "4.2.0"
81 | collection:
82 | dependency: transitive
83 | description:
84 | name: collection
85 | url: "https://pub.dartlang.org"
86 | source: hosted
87 | version: "1.16.0"
88 | convert:
89 | dependency: transitive
90 | description:
91 | name: convert
92 | url: "https://pub.dartlang.org"
93 | source: hosted
94 | version: "3.0.2"
95 | crypto:
96 | dependency: transitive
97 | description:
98 | name: crypto
99 | url: "https://pub.dartlang.org"
100 | source: hosted
101 | version: "3.0.2"
102 | dart_style:
103 | dependency: transitive
104 | description:
105 | name: dart_style
106 | url: "https://pub.dartlang.org"
107 | source: hosted
108 | version: "2.2.3"
109 | fake_async:
110 | dependency: transitive
111 | description:
112 | name: fake_async
113 | url: "https://pub.dartlang.org"
114 | source: hosted
115 | version: "1.3.0"
116 | file:
117 | dependency: transitive
118 | description:
119 | name: file
120 | url: "https://pub.dartlang.org"
121 | source: hosted
122 | version: "6.1.4"
123 | fixnum:
124 | dependency: transitive
125 | description:
126 | name: fixnum
127 | url: "https://pub.dartlang.org"
128 | source: hosted
129 | version: "1.0.1"
130 | flutter:
131 | dependency: "direct main"
132 | description: flutter
133 | source: sdk
134 | version: "0.0.0"
135 | flutter_lints:
136 | dependency: "direct dev"
137 | description:
138 | name: flutter_lints
139 | url: "https://pub.dartlang.org"
140 | source: hosted
141 | version: "2.0.1"
142 | flutter_test:
143 | dependency: "direct dev"
144 | description: flutter
145 | source: sdk
146 | version: "0.0.0"
147 | glob:
148 | dependency: transitive
149 | description:
150 | name: glob
151 | url: "https://pub.dartlang.org"
152 | source: hosted
153 | version: "2.1.0"
154 | lints:
155 | dependency: transitive
156 | description:
157 | name: lints
158 | url: "https://pub.dartlang.org"
159 | source: hosted
160 | version: "2.0.0"
161 | logging:
162 | dependency: transitive
163 | description:
164 | name: logging
165 | url: "https://pub.dartlang.org"
166 | source: hosted
167 | version: "1.0.2"
168 | matcher:
169 | dependency: transitive
170 | description:
171 | name: matcher
172 | url: "https://pub.dartlang.org"
173 | source: hosted
174 | version: "0.12.11"
175 | material_color_utilities:
176 | dependency: transitive
177 | description:
178 | name: material_color_utilities
179 | url: "https://pub.dartlang.org"
180 | source: hosted
181 | version: "0.1.5"
182 | meta:
183 | dependency: transitive
184 | description:
185 | name: meta
186 | url: "https://pub.dartlang.org"
187 | source: hosted
188 | version: "1.8.0"
189 | mockito:
190 | dependency: "direct dev"
191 | description:
192 | name: mockito
193 | url: "https://pub.dartlang.org"
194 | source: hosted
195 | version: "5.3.0"
196 | package_config:
197 | dependency: transitive
198 | description:
199 | name: package_config
200 | url: "https://pub.dartlang.org"
201 | source: hosted
202 | version: "2.1.0"
203 | path:
204 | dependency: transitive
205 | description:
206 | name: path
207 | url: "https://pub.dartlang.org"
208 | source: hosted
209 | version: "1.8.2"
210 | pub_semver:
211 | dependency: transitive
212 | description:
213 | name: pub_semver
214 | url: "https://pub.dartlang.org"
215 | source: hosted
216 | version: "2.1.1"
217 | sky_engine:
218 | dependency: transitive
219 | description: flutter
220 | source: sdk
221 | version: "0.0.99"
222 | source_gen:
223 | dependency: transitive
224 | description:
225 | name: source_gen
226 | url: "https://pub.dartlang.org"
227 | source: hosted
228 | version: "1.2.2"
229 | source_span:
230 | dependency: transitive
231 | description:
232 | name: source_span
233 | url: "https://pub.dartlang.org"
234 | source: hosted
235 | version: "1.9.0"
236 | stack_trace:
237 | dependency: transitive
238 | description:
239 | name: stack_trace
240 | url: "https://pub.dartlang.org"
241 | source: hosted
242 | version: "1.10.0"
243 | stream_channel:
244 | dependency: transitive
245 | description:
246 | name: stream_channel
247 | url: "https://pub.dartlang.org"
248 | source: hosted
249 | version: "2.1.0"
250 | string_scanner:
251 | dependency: transitive
252 | description:
253 | name: string_scanner
254 | url: "https://pub.dartlang.org"
255 | source: hosted
256 | version: "1.1.1"
257 | term_glyph:
258 | dependency: transitive
259 | description:
260 | name: term_glyph
261 | url: "https://pub.dartlang.org"
262 | source: hosted
263 | version: "1.2.0"
264 | test_api:
265 | dependency: transitive
266 | description:
267 | name: test_api
268 | url: "https://pub.dartlang.org"
269 | source: hosted
270 | version: "0.4.9"
271 | typed_data:
272 | dependency: transitive
273 | description:
274 | name: typed_data
275 | url: "https://pub.dartlang.org"
276 | source: hosted
277 | version: "1.3.1"
278 | vector_math:
279 | dependency: transitive
280 | description:
281 | name: vector_math
282 | url: "https://pub.dartlang.org"
283 | source: hosted
284 | version: "2.1.2"
285 | watcher:
286 | dependency: transitive
287 | description:
288 | name: watcher
289 | url: "https://pub.dartlang.org"
290 | source: hosted
291 | version: "1.0.1"
292 | yaml:
293 | dependency: transitive
294 | description:
295 | name: yaml
296 | url: "https://pub.dartlang.org"
297 | source: hosted
298 | version: "3.1.1"
299 | sdks:
300 | dart: ">=2.17.0 <3.0.0"
301 |
--------------------------------------------------------------------------------
/lib/src/controller.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/widgets.dart';
4 | import 'package:simple_map/simple_map.dart';
5 |
6 | import 'projections/miller_projection.dart';
7 | import 'projections/projection.dart';
8 |
9 | class SimpleMapController {
10 | SimpleMapController({
11 | this.showSpeedRate = 0.4,
12 | this.hideSpeedRate = 0.9,
13 | this.maxPointRadius = 4.0,
14 | this.shadowRatio = 1.5,
15 | this.shadowOpacity = 0.3,
16 | this.defaultPointTTL,
17 | this.radiusScaleFactors,
18 | this.glowRadius = 0.0,
19 | this.maxZoom = 7.0,
20 | points,
21 | }) : _points = points;
22 |
23 | /// [Point] showing animation speed factor
24 | final double showSpeedRate;
25 |
26 | /// [Point] hiding animation speed factor
27 | final double hideSpeedRate;
28 |
29 | /// The maximum [Point] radius
30 | final double maxPointRadius;
31 |
32 | /// [Point] shadow ratio
33 | final double shadowRatio;
34 |
35 | /// [Point] shadow opacity
36 | final double shadowOpacity;
37 |
38 | /// Default point time to live duration
39 | final Duration? defaultPointTTL;
40 |
41 | /// [Point] glow effect radius
42 | final double glowRadius;
43 |
44 | /// The maximum zoom of the map, used in [flyTo] animation
45 | final double maxZoom;
46 |
47 | /// Automatic [Point] radius based on [points.length]
48 | /// Example: {0: 1.7, 25: 1.4, 50: 1.2, 100: 1.0}
49 | final Map? radiusScaleFactors;
50 |
51 | double initialZoom = 1.0;
52 | Curve curve = Curves.linear;
53 |
54 | final List _markers = [];
55 | List? _points;
56 | Color? _defaultPointColor;
57 | Color? _startPointColor;
58 | int _lastTimeMs = 0;
59 |
60 | Offset? _tCenter;
61 | double _tZoom = 0.0;
62 | Size _size = Size.zero;
63 | State? _state;
64 |
65 | Animation? _centerAnim;
66 | Animation? _offsetAnim;
67 | Animation? _zoomAnim;
68 | AnimationController? _animation;
69 | AnimationController? _transformAnimation;
70 |
71 | SimpleMapProjection _projection = const MillerProjection();
72 |
73 | /// Active points list
74 | List? get points => _points;
75 |
76 | /// Active markers list
77 | List get markers => _markers;
78 |
79 | double get zoom => _zoomAnim?.value ?? initialZoom;
80 | Offset get center => _centerAnim?.value ?? Offset.zero;
81 | Offset get translation => _offsetAnim?.value ?? Offset.zero;
82 |
83 | // ignore: avoid_setters_without_getters
84 | set size(Size size) => _size = size;
85 |
86 | ///
87 | /// Add list of [points] to the map
88 | ///
89 | set points(List? points) {
90 | final tmp = points!.map((p) {
91 | if (p.color == null && _defaultPointColor != null) {
92 | p.color = _defaultPointColor;
93 | }
94 | p.targetRadius = maxPointRadius;
95 | if (_points == null) {
96 | p.state = SimpleMapPointState.active;
97 | }
98 | return p;
99 | }).toList();
100 | if (_points == null) {
101 | _points = tmp;
102 | } else {
103 | _points!.addAll(tmp);
104 | }
105 | }
106 |
107 | ///
108 | /// Add new [point] to the map
109 | ///
110 | void addPoint(SimpleMapPoint point) {
111 | if (point.color == null && _defaultPointColor != null) {
112 | point.color = _defaultPointColor;
113 | }
114 | point.targetRadius = maxPointRadius;
115 | if (_points == null) {
116 | _points = [point];
117 | } else {
118 | _points!.add(point);
119 | }
120 | }
121 |
122 | void addMarker(SimpleMapMarker marker) {
123 | _markers.add(marker);
124 | // TODO: refactory
125 | // ignore: invalid_use_of_protected_member
126 | _state?.setState(() {});
127 | }
128 |
129 | bool removeMarker(SimpleMapMarker marker) {
130 | if (_markers.remove(marker)) {
131 | // TODO: refactory
132 | // ignore: invalid_use_of_protected_member
133 | _state?.setState(() {});
134 | }
135 | return false;
136 | }
137 |
138 | void clearMarkers() {
139 | _markers.clear();
140 | }
141 |
142 | Offset project(double? lat, double? lng) {
143 | return _projection.project(lat, lng, _size);
144 | }
145 |
146 | ///
147 | /// Fly animation to the new [lat] and [lng]
148 | ///
149 | Future flyTo(
150 | double? lat,
151 | double? lng, {
152 | double zoom = 10,
153 | Duration duration = const Duration(milliseconds: 1500),
154 | }) async {
155 | _tZoom = min(maxZoom, zoom);
156 | _tCenter = project(lat, lng);
157 | _updateAnim();
158 | if (_transformAnimation != null) {
159 | // await _transformAnimation.animateBack(
160 | // 0.5,
161 | // duration: duration ?? const Duration(milliseconds: 500),
162 | // );
163 | // _transformAnimation.reset();
164 | await _transformAnimation!.animateTo(1.0, duration: duration);
165 | }
166 | }
167 |
168 | void _updateAnim() {
169 | if (_transformAnimation == null || _tCenter == null) {
170 | return;
171 | }
172 |
173 | _centerAnim = Tween(begin: project(0, 0), end: _tCenter).animate(
174 | CurvedAnimation(
175 | parent: _transformAnimation!,
176 | curve: Curves.ease,
177 | ),
178 | );
179 |
180 | _offsetAnim = Tween(
181 | begin: Offset.zero,
182 | end: Offset(
183 | 0.5 - _tCenter!.dx / _size.width,
184 | 0.5 - _tCenter!.dy / _size.height,
185 | ),
186 | ).animate(CurvedAnimation(
187 | parent: _transformAnimation!,
188 | curve: Curves.ease,
189 | ));
190 |
191 | // TODO: refactory
192 | _zoomAnim = Tween(begin: initialZoom, end: _tZoom).animate(
193 | CurvedAnimation(
194 | parent: _transformAnimation!,
195 | curve: Curves.ease,
196 | ),
197 | );
198 | }
199 |
200 | ///
201 | /// Configure
202 | ///
203 | void configure({
204 | required SimpleMapOptions options,
205 | Animation? animation,
206 | Animation? transformAnimation,
207 | State? state,
208 | }) {
209 | _state = state;
210 | _defaultPointColor = options.pointColor ?? _defaultPointColor;
211 | _startPointColor = options.startPointColor ?? _startPointColor;
212 | _projection = options.projection;
213 | _animation = animation as AnimationController? ?? _animation;
214 | _transformAnimation =
215 | transformAnimation as AnimationController? ?? _transformAnimation;
216 | }
217 |
218 | ///
219 | /// Clear the map
220 | ///
221 | void clear() {
222 | debugPrint('[$runtimeType] Clear points');
223 | if (_points != null) {
224 | _points!.clear();
225 | }
226 | _markers.clear();
227 | }
228 |
229 | void stopAnimation() {
230 | if (_animation != null && _animation!.isAnimating) {
231 | _animation?.stop();
232 | }
233 | if (_points != null) {
234 | _points!.removeWhere((p) => p.state != SimpleMapPointState.active);
235 | }
236 | }
237 |
238 | void startAnimation() {
239 | if (_animation != null && !_animation!.isAnimating) {
240 | _animation!.repeat();
241 | }
242 | }
243 |
244 | double _interpolateWithEasing(double min, double max, double t) {
245 | final lerp = (t - min) / (max - min);
246 | return lerp;
247 | // return Curves.easeIn.transform(lerp);
248 | }
249 |
250 | ///
251 | /// Calculate point radius scale factor
252 | ///
253 | get _pointRadiusScaleFactor {
254 | double pointRadiusScaleFactor = 1.0;
255 | if (radiusScaleFactors?.isNotEmpty == true) {
256 | radiusScaleFactors!.forEach((sizeFrom, scaleFactor) {
257 | if (_points!.length >= sizeFrom) {
258 | pointRadiusScaleFactor = scaleFactor;
259 | }
260 | });
261 | }
262 | if (pointRadiusScaleFactor <= 0) {
263 | pointRadiusScaleFactor = 1.0;
264 | }
265 | return pointRadiusScaleFactor;
266 | }
267 |
268 | ///
269 | /// This method render [points] on the [canvas]
270 | /// based on the [size].
271 | ///
272 | void render(Canvas canvas, Size size) {
273 | var delta = 0.0;
274 | if (_animation != null) {
275 | final _newLastTimeMs =
276 | _animation!.lastElapsedDuration?.inMilliseconds ?? 0;
277 | delta = (_newLastTimeMs - _lastTimeMs) / Duration.millisecondsPerSecond;
278 | _lastTimeMs = _newLastTimeMs;
279 | }
280 |
281 | if (_points == null || _points!.isEmpty) {
282 | return;
283 | }
284 |
285 | final paint = Paint();
286 |
287 | _points!.removeWhere(
288 | (point) => point.state == SimpleMapPointState.inactive,
289 | );
290 |
291 | // print(_points!.where((element) => element.state != SimpleMapPointState.active));
292 |
293 | for (final point in _points!) {
294 | // TODO: refactory
295 | final animation = AlwaysStoppedAnimation(
296 | max(
297 | 0.0,
298 | 1.0 - _interpolateWithEasing(0.0, maxPointRadius, point.targetRadius),
299 | ),
300 | );
301 |
302 | if (_updatePoint(point, delta, animation.value)) {
303 | if (point.targetColor == null) {
304 | continue;
305 | }
306 |
307 | final center = _projection.project(point.lat, point.lng, size);
308 | if (center.dx.isNaN || center.dy.isNaN) {
309 | continue;
310 | }
311 |
312 | final pointRadius = point.radius * _pointRadiusScaleFactor;
313 |
314 | // if (point.state == SimpleMapPointState.showing) {
315 | // radius = point.targetRadius;
316 | // }
317 |
318 | final radius = point.targetRadius > maxPointRadius
319 | ? pointRadius
320 | : point.targetRadius * _pointRadiusScaleFactor;
321 |
322 | final color = point.targetColor!.withOpacity(
323 | point.opacity.toDouble().clamp(0.0, 1.0),
324 | );
325 |
326 | canvas.drawCircle(center, radius, paint..color = color);
327 |
328 | if (glowRadius > 0) {
329 | canvas.drawShadow(
330 | Path()
331 | ..addOval(
332 | Rect.fromCircle(
333 | center: center.translate(0, -glowRadius),
334 | radius: radius,
335 | ),
336 | ),
337 | color,
338 | glowRadius,
339 | false,
340 | );
341 | }
342 |
343 | // disabled animation
344 | if (_animation == null) {
345 | continue;
346 | }
347 |
348 | /// Generate [point] shadow effect
349 | ///
350 | // if (point.state == SimpleMapPointState.showing || point.state == SimpleMapPointState.active) {
351 | if (point.state == SimpleMapPointState.showing) {
352 | if (point.animator != null) {
353 | point.animator!.render(
354 | point: point,
355 | animation: animation,
356 | canvas: canvas,
357 | center: center,
358 | );
359 | } else if (shadowRatio > 0) {
360 | // Default point animator
361 | // var radius = point.targetRadius * shadowRatio;
362 | // var rect = Rect.fromCircle(center: center, radius: radius);
363 | final radius = Tween(
364 | begin: 0.0,
365 | end: min(point.targetRadius * shadowRatio, pointRadius * 5),
366 | ).animate(
367 | CurvedAnimation(
368 | parent: animation,
369 | curve: const Interval(0.0, 0.3, curve: Curves.easeOutBack),
370 | ),
371 | );
372 | final opacity = Tween(begin: shadowOpacity, end: 0.0).animate(
373 | CurvedAnimation(
374 | parent: animation,
375 | curve: const Interval(0.0, 0.3, curve: Curves.easeInOut),
376 | ),
377 | );
378 |
379 | canvas.drawCircle(
380 | center,
381 | radius.value,
382 | paint..color = point.targetColor!.withOpacity(opacity.value),
383 | );
384 | }
385 | }
386 | }
387 | }
388 | }
389 |
390 | ///
391 | /// This method updates the [point] when [render] was called.
392 | ///
393 | bool _updatePoint(SimpleMapPoint point, double delta, double t) {
394 | switch (point.state) {
395 | case SimpleMapPointState.idle:
396 | point.opacity = 1.0;
397 | point.targetRadius = maxPointRadius;
398 | point.targetColor = _startPointColor ?? point.color;
399 | if (point.ttl == Duration.zero && defaultPointTTL != null) {
400 | point.ttl = defaultPointTTL;
401 | }
402 | if (_animation?.lastElapsedDuration != null) {
403 | point.ttl = Duration(
404 | milliseconds: _animation!.lastElapsedDuration!.inMilliseconds +
405 | point.ttl!.inMilliseconds,
406 | );
407 | }
408 | point.state = SimpleMapPointState.showing;
409 | continue showing;
410 | showing:
411 | case SimpleMapPointState.showing:
412 | point.targetColor = Color.lerp(
413 | _startPointColor ?? point.color,
414 | point.color ?? _defaultPointColor,
415 | t,
416 | );
417 | point.targetRadius -= delta * showSpeedRate;
418 | // if (point.targetRadius <= point.radius) {
419 | if (point.targetRadius <= 0) {
420 | point.state = SimpleMapPointState.active;
421 | continue active;
422 | }
423 | break;
424 | active:
425 | case SimpleMapPointState.active:
426 | point.opacity = 1.0;
427 | point.targetRadius = point.radius;
428 | point.targetColor =
429 | point.color ?? _defaultPointColor; // TODO: is it need ?
430 | if (_animation?.lastElapsedDuration != null &&
431 | point.ttl! < _animation!.lastElapsedDuration!) {
432 | point.state = SimpleMapPointState.hiding;
433 | continue hiding;
434 | }
435 | break;
436 | hiding:
437 | case SimpleMapPointState.hiding:
438 | // point.opacity = lerpDouble(point.opacity, 0.0, hideSpeed);
439 | point.opacity -= delta * hideSpeedRate;
440 | if (point.opacity <= 0.0) {
441 | point
442 | ..state = SimpleMapPointState.inactive
443 | ..opacity = 0.0;
444 | continue inactive;
445 | }
446 | break;
447 | inactive:
448 | case SimpleMapPointState.inactive:
449 | return false;
450 | }
451 |
452 | return true;
453 | }
454 | }
455 |
--------------------------------------------------------------------------------
/example/assets/points.json:
--------------------------------------------------------------------------------
1 | [["17.5","106.6"],["35.9","47.6"],["39.7","-76.9"],["-19.6","18.1"],["41.0","71.7"],["42.8","132.9"],["35.9","126.9"],["-3.4","-44.4"],["46.3","18.7"],["-22.7","-64.4"],["7.0","125.1"],["57.0","22.8"],["46.8","-100.8"],["30.3","-98.0"],["44.3","21.1"],["-32.6","-69.3"],["40.0","44.6"],["40.7","-73.4"],["30.7","111.3"],["41.9","-103.7"],["42.0","-76.5"],["64.2","27.7"],["38.9","-76.6"],["10.4","-71.5"],["6.1","125.3"],["16.6","-24.4"],["-3.9","30.0"],["55.7","84.9"],["44.3","-90.8"],["64.1","-139.4"],["38.8","-77.3"],["41.6","-73.4"],["47.7","-104.2"],["6.5","-71.7"],["20.5","-90.1"],["12.3","-2.4"],["33.8","-96.6"],["35.7","0.6"],["40.1","-74.7"],["41.6","14.7"],["42.7","-71.4"],["-0.9","134.1"],["62.2","-7.0"],["41.5","-88.1"],["11.3","49.2"],["15.5","121.1"],["-26.2","-58.2"],["47.3","29.1"],["39.1","-77.1"],["46.3","44.2"],["57.8","36.7"],["55.7","52.3"],["7.2","5.6"],["-17.6","36.8"],["-26.1","-66.0"],["47.7","-117.2"],["28.1","-97.8"],["-26.2","-54.6"],["42.5","-75.5"],["47.4","28.8"],["13.1","44.9"],["36.9","43.0"],["38.6","-122.6"],["36.6","-82.5"],["41.4","-74.5"],["42.0","22.6"],["35.4","-80.9"],["34.9","5.7"],["16.6","-7.3"],["27.7","106.9"],["40.4","-74.4"],["36.8","66.9"],["50.4","18.9"],["54.6","23.0"],["10.5","106.4"],["36.7","-82.0"],["12.6","99.9"],["43.1","-77.1"],["29.2","-82.2"],["39.8","39.5"],["42.1","-83.3"],["50.0","92.1"],["-1.3","-80.6"],["24.1","120.5"],["46.3","15.7"],["-17.8","15.7"],["32.5","74.6"],["34.7","-82.8"],["48.1","-98.9"],["45.8","-108.4"],["-11.0","-38.8"],["27.6","68.2"],["38.0","-79.0"],["42.2","-71.7"],["32.8","-109.8"],["53.4","-117.6"],["40.3","-74.0"],["69.6","19.0"],["24.8","-107.4"],["27.5","83.4"],["23.6","90.5"],["43.9","143.9"],["25.4","55.4"],["34.2","74.4"],["-22.7","-47.6"],["35.0","-110.7"],["30.4","-86.5"],["35.9","-79.0"],["42.1","-76.9"],["34.6","-112.4"],["-4.0","19.5"],["42.9","-8.5"],["37.6","-93.4"],["1.3","-78.9"],["30.5","-92.1"],["36.1","-78.8"],["56.2","37.0"],["5.3","-4.4"],["29.5","-95.1"],["43.6","104.4"],["-15.5","167.2"],["41.4","-74.7"],["47.6","-122.6"],["41.1","-74.0"],["44.1","-70.2"],["42.1","-87.8"],["54.6","39.7"],["42.9","21.2"],["38.9","-94.3"],["45.6","14.2"],["46.1","-72.0"],["22.2","-101.0"],["-38.7","176.1"],["-1.8","37.6"],["9.4","16.3"],["-41.0","-70.3"],["43.1","-77.3"],["10.3","-3.2"],["41.0","-92.0"],["16.8","94.8"],["30.3","-95.5"],["27.0","84.9"],["34.4","-117.5"],["31.5","92.1"],["33.2","-86.3"],["39.1","-82.5"],["35.5","44.4"],["40.0","-82.0"],["41.4","-82.7"],["20.3","100.4"],["6.8","29.7"],["53.6","-2.3"],["33.7","-84.3"],["33.0","-93.5"],["8.0","3.6"],["-33.2","-54.4"],["42.4","-71.3"],["36.3","127.4"],["29.4","113.1"],["39.5","-118.8"],["42.1","-87.7"],["62.7","135.6"],["42.3","-84.0"],["35.6","6.2"],["35.4","-96.0"],["43.9","20.7"],["37.1","-81.8"],["39.7","-87.4"],["-30.1","-51.2"],["61.5","21.8"],["23.7","90.4"],["43.6","-84.2"],["25.0","98.5"],["-5.9","28.0"],["38.6","-77.1"],["43.0","47.5"],["34.5","-85.8"],["13.1","103.2"],["32.4","-97.4"],["21.5","39.2"],["40.2","-76.2"],["32.7","-102.0"],["5.0","118.3"],["37.0","-120.6"],["-9.4","159.9"],["47.3","123.2"],["-1.5","40.0"],["9.4","-70.4"],["53.7","-3.0"],["41.1","14.3"],["45.8","9.1"],["-20.8","-49.4"],["5.8","7.0"],["-1.1","35.9"],["36.8","-97.3"],["37.6","127.0"],["6.1","100.4"],["37.6","-77.6"],["-19.5","169.3"],["53.5","-2.3"],["40.1","-85.7"],["41.9","-72.6"],["45.6","-89.4"],["7.4","151.9"],["28.4","-11.1"],["32.1","-81.3"],["41.9","-71.5"],["22.7","-4.0"],["-14.5","30.8"],["11.9","-86.0"],["54.9","64.4"],["-7.1","-41.4"],["33.2","-86.8"],["68.8","16.5"],["43.8","-88.8"],["46.9","28.8"],["44.7","-81.1"],["36.3","-95.3"],["41.3","-80.7"],["41.5","-72.8"],["34.0","-98.7"],["60.7","-135.1"],["33.4","-110.8"],["45.5","-122.7"],["14.7","-17.5"],["67.9","32.8"],["52.0","7.6"],["41.6","69.7"],["34.0","-118.1"],["37.7","-122.5"],["7.1","-73.9"],["47.9","35.2"],["43.2","-72.4"],["60.0","-111.9"],["42.6","-71.1"],["10.3","22.8"],["33.6","-84.3"],["36.2","-86.6"],["53.7","-57.0"],["37.1","37.4"],["46.3","-119.1"],["41.1","108.3"],["34.5","-118.6"],["37.1","-122.1"],["16.7","74.2"],["-8.1","-39.1"],["13.0","42.7"],["-22.1","-70.2"],["52.9","-102.4"],["33.2","-92.7"],["34.0","-118.3"],["-38.6","-58.8"],["32.5","-117.1"],["34.7","-81.6"],["42.6","-83.9"],["57.1","24.3"],["3.2","113.0"],["-3.1","-60.0"],["51.6","-3.0"],["42.1","-91.3"],["-47.8","-65.9"],["1.4","31.3"],["32.1","-111.3"],["51.5","0.1"],["34.2","-118.9"],["10.6","-61.3"],["67.0","-171.8"],["-12.8","15.8"],["33.6","46.4"],["42.7","-87.9"],["37.0","-121.7"],["29.6","-95.6"],["25.0","121.6"],["53.0","116.9"],["21.5","109.1"],["-30.4","137.2"],["38.1","-89.4"],["38.4","-122.7"],["-9.3","125.3"],["1.6","16.1"],["42.4","59.5"],["43.5","-76.4"],["46.0","-66.6"],["43.0","-71.7"],["42.3","21.4"],["26.1","-80.1"],["-15.2","19.2"],["34.3","-77.9"],["27.0","111.2"],["-36.3","-57.7"],["15.0","-91.1"],["48.9","38.4"],["-23.6","-51.5"],["29.7","-91.3"],["40.2","-74.1"],["45.8","-122.7"],["39.8","-7.5"],["28.9","-82.4"],["33.6","-86.6"],["30.4","-87.2"],["40.7","-73.5"],["43.1","25.7"],["-27.1","31.2"],["49.3","120.7"],["42.4","-71.9"],["54.9","37.4"],["33.5","-86.9"],["41.9","-83.4"],["38.5","-28.6"],["46.1","14.0"],["8.1","-81.0"],["28.1","-81.6"],["1.6","30.2"],["26.6","-81.7"],["39.7","-105.1"],["-21.2","-50.5"],["31.6","-103.0"],["44.6","-75.7"],["42.0","-71.9"],["30.4","-88.5"],["42.4","-82.9"],["45.9","40.1"],["34.7","33.0"],["-31.7","116.7"],["41.6","-73.1"],["-2.5","-44.3"],["51.0","-118.2"],["39.4","-104.8"],["14.6","46.8"],["-6.4","20.8"],["56.7","66.3"],["54.4","23.2"],["40.5","68.8"],["9.0","-79.5"],["37.7","-85.9"],["47.5","-79.7"],["35.3","-89.9"],["55.9","-3.2"],["41.1","-82.7"],["41.3","-89.1"],["2.2","73.1"],["15.7","100.1"],["40.4","-120.6"],["38.3","-76.4"],["42.5","-83.0"],["63.8","121.6"],["6.9","-6.5"],["15.0","120.7"],["33.4","-82.1"],["56.5","27.9"],["38.5","-82.6"],["29.6","106.6"],["41.1","-80.1"],["47.6","18.4"],["39.4","-107.0"],["32.1","114.1"],["50.1","8.3"],["3.7","18.6"],["28.1","-81.7"],["41.2","20.4"],["54.9","41.4"],["29.5","77.7"],["36.1","-79.3"],["27.8","-98.1"],["-23.0","-45.6"],["37.4","-77.7"],["45.5","8.6"],["20.7","-105.2"],["40.1","-74.2"],["53.2","87.3"],["39.7","-76.7"],["4.8","11.2"],["60.9","26.7"],["33.6","-86.5"],["48.5","32.3"],["-35.7","-63.8"],["35.3","113.9"],["-12.2","44.4"],["-0.9","122.8"],["20.6","58.9"],["40.6","-74.6"],["-26.3","28.4"],["54.6","-6.7"],["36.2","-86.8"],["40.1","-76.2"],["1.6","7.4"],["56.5","25.9"],["42.2","-78.7"],["45.6","-62.6"],["44.0","20.5"],["42.8","-71.2"],["0.0","-51.1"],["35.5","-120.7"],["-25.3","-59.7"],["41.4","-71.7"],["31.8","120.0"],["39.7","-84.1"],["51.7","75.3"],["37.8","-3.8"],["40.3","-88.2"],["41.6","-87.7"],["33.6","-85.9"],["36.0","119.4"],["38.1","46.3"],["53.5","49.5"],["29.1","-98.2"],["13.5","2.1"],["56.5","23.4"],["45.9","20.1"],["40.7","-85.2"],["45.9","-122.8"],["0.1","37.6"],["-42.7","171.0"],["10.6","51.1"],["33.6","-117.3"],["44.9","110.2"],["58.7","-111.2"],["-6.5","-78.7"],["42.0","-88.3"],["42.6","-71.4"],["10.8","79.2"],["37.1","140.9"],["71.4","136.1"],["41.2","-80.1"],["60.2","24.9"],["32.7","-103.2"],["43.6","10.3"],["-17.8","-50.9"],["64.0","-22.6"],["6.8","38.4"],["6.4","-10.6"],["45.4","-122.6"],["56.1","12.7"],["46.2","15.6"],["40.2","-76.6"],["40.1","-104.9"],["36.1","35.9"],["-26.4","146.3"],["41.1","-73.4"],["44.3","-105.5"],["42.2","24.8"],["30.8","-88.1"],["30.3","-94.2"],["58.7","29.8"],["40.1","65.4"],["26.3","-80.1"],["15.9","-86.0"],["35.2","-81.2"],["39.9","69.0"],["42.2","-71.5"],["30.8","-85.2"],["42.6","-71.0"],["37.0","-93.7"],["54.6","52.8"],["33.1","-94.2"],["54.3","-7.6"],["45.8","-108.6"],["41.6","43.0"],["40.9","-72.6"],["20.9","94.8"],["46.9","-122.6"],["36.6","-119.6"],["41.6","-70.9"],["9.4","-64.5"],["35.1","-97.4"],["28.3","-82.7"],["39.0","-119.7"],["-29.1","-59.3"],["30.3","-95.1"],["40.2","44.5"],["33.6","-86.1"],["53.5","-112.1"],["37.3","40.7"],["51.0","1.8"],["30.4","-91.0"],["54.2","19.4"],["40.5","-79.9"],["50.7","17.9"],["35.9","-81.2"],["12.1","1.8"],["36.3","-82.2"],["29.9","-95.6"],["33.9","-81.5"],["18.0","-76.8"],["-7.6","110.8"],["38.9","-94.4"],["-11.0","-68.7"],["10.0","-10.8"],["41.0","-72.2"],["40.3","-103.6"],["-2.9","32.2"],["42.1","-94.9"],["47.2","27.8"],["40.5","-111.9"],["42.2","-71.9"],["25.3","110.3"],["43.1","-76.4"],["13.7","-88.1"],["18.5","-67.0"],["33.3","-0.3"],["-15.0","22.7"],["36.7","-84.2"],["45.8","133.0"],["28.6","112.3"],["65.5","72.5"],["39.0","-94.5"],["14.3","-16.4"],["16.2","-61.5"],["9.1","6.0"],["-45.6","-69.1"],["56.2","95.7"],["43.3","-73.5"],["46.5","15.8"],["24.8","112.4"],["60.9","76.6"],["35.0","-85.7"],["-4.5","136.9"],["-2.9","-44.3"],["42.0","-72.3"],["35.6","-97.6"],["-17.4","-66.2"],["42.9","-87.9"],["54.8","-66.8"],["44.9","18.8"],["-19.2","-64.9"],["34.3","-82.9"],["29.5","-81.1"],["-9.3","-38.3"],["42.3","-83.1"],["9.3","-82.4"],["47.2","-122.5"],["46.0","9.0"],["24.2","47.3"],["49.1","6.2"],["-13.5","25.8"],["35.5","-80.6"],["40.5","-80.0"],["44.8","10.3"],["36.5","-86.0"],["-28.6","-70.8"],["30.4","-88.7"],["40.1","70.8"],["35.7","-77.9"],["25.7","28.9"],["11.1","-0.2"],["37.8","-113.0"],["39.9","-86.0"],["2.3","34.3"],["40.6","-91.4"],["56.9","24.3"],["47.8","-116.8"],["33.0","-80.0"],["29.7","-95.1"],["37.5","34.1"],["16.2","52.2"],["34.7","-120.5"],["45.7","14.7"],["30.6","-97.4"],["30.4","-97.4"],["42.3","-77.7"],["42.6","20.6"],["-43.1","-73.6"],["-19.7","-50.2"],["45.6","13.7"],["-52.7","-71.5"],["30.2","-97.6"],["14.0","108.0"],["42.4","-79.4"],["0.8","32.4"],["33.6","36.4"],["35.1","-85.2"],["13.9","-4.6"],["-15.6","-56.1"],["0.2","30.0"],["-6.7","156.4"],["43.3","-88.3"],["33.7","-117.2"],["40.5","-111.4"],["29.0","118.9"],["20.0","-102.3"],["40.2","-77.2"],["31.5","-83.5"],["-3.9","-70.5"],["45.7","13.8"],["31.8","35.2"],["-10.7","165.9"],["41.8","-73.0"],["42.1","-71.0"],["8.6","-70.3"],["37.8","-94.3"],["44.2","-86.3"],["-30.9","-55.5"],["-0.5","37.5"],["33.7","-116.3"],["43.0","-96.1"],["36.1","-97.1"],["43.5","-110.8"],["-3.2","40.1"],["22.7","106.3"],["-13.2","-43.4"],["12.5","-15.2"],["-20.9","29.0"],["51.6","0.1"],["32.4","-91.2"],["28.7","-81.3"],["33.0","-112.0"],["19.1","74.8"],["40.7","-74.2"],["-11.1","-75.3"],["54.5","90.0"],["32.8","-97.4"],["0.6","-80.0"],["38.9","-77.0"],["-3.7","-43.4"],["57.0","25.0"],["58.8","17.0"],["45.5","14.7"],["31.6","106.0"],["44.9","-93.7"],["53.3","-6.1"],["35.5","-92.0"],["24.3","109.3"],["31.6","130.6"],["31.5","-110.2"],["53.9","30.3"],["-37.5","-61.9"],["43.6","21.9"],["43.4","19.4"],["3.3","32.9"],["-3.7","-40.4"],["43.2","-78.2"],["38.8","-77.5"],["55.4","55.5"],["36.4","-99.4"],["42.2","-122.7"],["58.9","57.6"],["41.3","-122.3"],["43.1","-75.8"],["29.0","-95.4"],["20.9","-156.5"],["40.5","-86.1"],["-22.7","-47.3"],["35.5","139.7"],["-4.9","29.6"],["7.3","134.5"],["12.3","104.7"],["36.3","-82.4"],["-10.0","39.7"],["22.9","-105.8"],["36.2","-79.9"],["-5.6","12.2"],["-8.0","-34.9"],["34.9","-1.3"],["42.0","21.4"],["39.1","-95.1"],["36.1","103.8"],["5.9","5.7"],["43.4","77.4"],["23.4","88.5"],["-13.7","19.9"],["-13.9","-171.5"],["40.3","-78.9"],["26.3","31.9"],["10.6","103.5"],["52.7","15.2"],["30.4","-89.1"],["0.8","32.5"],["-17.4","-63.7"],["48.1","-1.7"],["39.0","-94.7"],["-4.7","11.8"],["56.1","60.2"],["43.4","-84.6"],["35.6","-77.4"],["41.0","21.5"],["7.6","4.2"],["40.9","-72.8"],["28.4","-81.3"],["35.6","-82.6"],["38.9","-95.1"],["15.3","-83.8"],["-26.8","153.1"],["44.4","21.0"],["41.0","-73.8"],["23.3","69.8"],["14.8","-88.8"],["26.3","105.9"],["39.3","-76.4"],["34.9","-85.2"],["53.0","-112.8"],["40.6","43.1"],["8.9","17.6"],["50.0","82.6"],["34.1","-117.4"],["50.7","-2.0"],["3.1","43.7"],["40.7","-78.2"],["39.3","46.6"],["4.9","-52.3"],["-16.9","-64.8"],["39.9","-84.2"],["37.9","-82.0"],["32.3","75.7"],["44.5","-93.2"],["36.7","-80.9"],["42.2","22.3"],["41.3","-72.1"],["40.0","-74.2"],["34.2","-79.3"],["68.0","123.4"],["32.4","105.9"],["34.1","-84.1"],["35.5","-108.7"],["-38.4","-60.3"],["39.1","-104.7"],["-32.9","-68.8"],["17.5","101.7"],["41.7","-74.7"],["34.1","-81.2"],["42.3","-83.7"],["38.4","-78.8"],["-6.0","39.3"],["6.6","0.5"],["-13.4","-172.3"],["35.5","-78.7"],["51.3","0.5"],["30.1","-89.9"],["49.9","-124.6"],["2.5","31.1"],["12.6","-11.4"],["42.3","-72.4"],["-15.3","-49.6"],["41.6","-88.1"],["9.5","-7.6"],["34.7","135.2"],["38.4","-122.8"],["-28.7","24.8"],["42.5","22.5"],["39.6","47.1"],["34.1","-99.3"],["0.8","33.7"],["46.4","-94.2"],["41.2","-73.6"],["34.5","109.5"],["48.1","-122.2"],["-6.8","30.4"],["-7.4","-79.6"],["6.8","79.9"],["27.5","-81.5"],["-22.5","-43.2"],["13.2","123.8"],["35.8","-78.6"],["-2.9","12.7"],["33.3","-87.6"],["-12.8","45.3"],["44.7","-73.6"],["34.5","-89.0"],["41.7","-73.6"],["46.5","16.3"],["50.9","7.0"],["33.9","10.1"],["47.8","-3.4"],["40.8","-74.1"],["1.8","98.8"],["49.8","-94.5"],["44.3","20.7"],["11.1","-12.4"],["35.3","-81.0"],["35.0","-90.8"],["32.7","-111.6"],["35.0","69.3"],["51.2","33.2"],["32.6","-96.3"],["22.0","-159.3"],["45.3","-122.6"],["41.5","-87.6"],["56.5","85.0"],["20.0","42.6"],["42.6","21.4"],["-12.9","34.3"],["29.8","-96.2"],["16.3","-86.5"],["35.0","-101.9"],["36.8","3.1"],["37.7","-84.3"],["45.1","21.0"],["41.3","19.8"],["42.2","-72.7"],["-32.6","149.6"],["52.7","62.6"],["54.3","26.9"],["39.9","-88.9"],["51.4","-0.1"],["53.8","127.3"],["42.8","-88.2"],["-37.0","174.9"],["36.3","-88.3"],["24.9","-98.2"],["44.6","21.3"],["27.3","86.1"],["6.2","31.6"],["49.7","83.4"],["36.7","-88.6"],["43.1","-94.2"],["-29.2","-67.5"],["28.6","17.6"],["53.6","-0.7"],["53.5","-2.2"],["13.1","109.3"],["39.1","-94.9"],["36.8","-114.1"],["9.9","13.9"],["-6.0","-44.2"],["56.4","21.9"],["14.4","108.0"],["36.2","-93.1"],["40.0","-83.0"],["46.4","16.2"],["42.2","-88.2"],["38.3","-85.7"],["-3.3","31.0"],["34.9","35.9"],["-23.1","-64.3"],["44.6","18.7"],["36.8","-94.4"],["3.5","73.5"],["39.4","53.1"],["43.0","-83.6"],["28.6","-81.4"],["39.7","-75.3"],["29.8","-90.0"],["44.7","-75.5"],["30.5","-97.8"],["61.5","-6.9"],["-14.9","50.3"],["-7.3","27.5"],["46.7","-117.0"],["-32.7","151.6"],["36.6","127.5"],["40.1","-84.6"],["31.6","-91.6"],["44.1","43.1"],["38.8","-76.1"],["26.9","75.8"],["41.2","-96.1"],["-18.4","-66.6"],["36.6","-79.4"],["44.9","-89.6"],["-21.7","21.6"],["-33.1","-68.5"],["33.7","-84.1"],["40.7","19.6"],["40.2","-104.9"],["7.9","9.8"],["58.1","52.6"],["43.7","7.4"],["-29.7","152.9"],["-11.4","-75.7"],["31.0","61.5"],["42.2","-73.7"],["31.4","-110.9"],["21.2","-101.7"],["-26.5","31.4"],["15.9","104.6"],["-16.5","-54.6"],["42.2","-73.9"],["42.2","-122.8"],["19.6","-155.9"],["19.3","-99.7"],["5.0","25.1"],["40.7","-89.5"],["51.5","0.2"],["42.4","-71.4"],["-6.7","111.0"],["37.6","-84.3"],["29.8","-95.0"],["7.7","28.0"],["-32.2","121.8"],["39.9","-85.4"],["-1.0","37.1"],["12.9","10.5"],["4.3","18.6"],["-10.8","-65.3"],["18.4","-67.2"],["-18.7","-39.9"],["18.8","-69.8"],["44.6","-123.3"],["46.4","15.1"],["21.2","-104.9"],["44.9","26.0"],["28.7","77.4"],["56.6","24.2"],["-34.1","-59.0"],["36.0","-106.1"],["40.7","31.6"],["54.9","46.6"],["32.3","-111.3"],["39.0","-76.9"],["40.2","-77.0"],["53.8","-0.4"],["11.3","-5.7"],["35.1","-114.5"],["43.0","-74.3"],["20.6","106.1"],["34.9","-118.2"],["36.1","-5.5"],["-27.5","-70.3"],["36.6","127.3"],["21.2","81.6"],["54.2","-125.8"],["49.6","6.0"],["40.9","-77.8"],["37.7","-88.9"],["-16.1","-68.7"],["40.3","-86.5"],["33.7","-85.8"],["41.4","2.2"],["-24.1","34.7"],["53.2","50.2"],["5.0","-6.1"],["-14.3","-178.2"],["44.6","33.5"],["42.9","-83.5"],["33.0","-82.8"],["41.1","111.4"],["37.6","-77.5"],["-15.8","-70.0"],["40.0","-74.8"],["30.2","115.1"],["-21.2","24.9"],["46.8","28.6"],["31.6","-8.0"],["36.4","55.0"],["26.2","-98.1"],["-27.0","24.7"],["34.1","-117.5"],["-22.2","-45.9"],["8.5","77.0"],["39.5","-74.6"],["42.9","-71.4"],["54.0","24.0"],["45.4","-85.0"],["40.6","-80.6"],["-34.5","-56.3"],["57.0","24.6"],["-2.9","29.8"],["7.0","40.0"],["40.7","-89.6"],["62.2","-75.7"],["49.0","-88.3"],["39.2","-74.8"],["12.1","24.9"],["-48.8","-70.3"],["-27.4","29.9"],["30.5","-84.3"],["32.8","-97.2"],["3.0","30.9"],["47.0","32.0"],["42.0","-87.7"],["42.5","-94.2"],["43.6","1.4"],["-37.6","-73.7"],["-8.1","159.6"],["38.5","-77.4"],["-33.8","25.4"],["38.8","-108.1"],["-20.2","57.5"],["0.4","37.6"],["37.2","-77.4"],["30.6","-98.4"],["-6.1","145.4"],["33.8","-84.6"],["-30.2","27.5"],["38.4","-104.7"],["-27.4","23.4"],["-34.0","20.4"],["35.0","-90.1"],["-53.2","-70.9"],["26.2","68.4"],["39.4","-94.8"],["37.2","28.4"],["41.6","-73.0"],["9.4","-13.1"],["28.3","-81.6"],["42.6","1.5"],["-13.8","-171.9"],["11.8","41.0"],["40.6","-89.5"],["43.7","127.3"],["45.1","-123.4"],["-1.4","29.7"],["31.8","-81.6"],["42.2","-85.9"],["-6.1","39.3"],["33.5","-82.1"],["51.9","116.0"],["45.3","21.9"],["47.4","-122.2"],["41.3","-87.4"],["-37.9","175.5"]]
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 51;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 6D3221E2F82CCF365D0BFBF7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67D3DF48EF3F1662CA1280CB /* Pods_Runner.framework */; };
13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = "";
24 | dstSubfolderSpec = 10;
25 | files = (
26 | );
27 | name = "Embed Frameworks";
28 | runOnlyForDeploymentPostprocessing = 0;
29 | };
30 | /* End PBXCopyFilesBuildPhase section */
31 |
32 | /* Begin PBXFileReference section */
33 | 02FD240E0528C9835C59764A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
34 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
35 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
37 | 67D3DF48EF3F1662CA1280CB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
38 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
39 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
41 | 7C2133D4597D4CCEDF729DAC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
42 | 8E474D2D282D9C736CA9FCCE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
43 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
44 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
45 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
47 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
48 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
49 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
50 | /* End PBXFileReference section */
51 |
52 | /* Begin PBXFrameworksBuildPhase section */
53 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | 6D3221E2F82CCF365D0BFBF7 /* Pods_Runner.framework in Frameworks */,
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | 03BD3683861262A284DE8696 /* Pods */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 8E474D2D282D9C736CA9FCCE /* Pods-Runner.debug.xcconfig */,
68 | 7C2133D4597D4CCEDF729DAC /* Pods-Runner.release.xcconfig */,
69 | 02FD240E0528C9835C59764A /* Pods-Runner.profile.xcconfig */,
70 | );
71 | path = Pods;
72 | sourceTree = "";
73 | };
74 | 5A3A443C3765CAFB65484AC2 /* Frameworks */ = {
75 | isa = PBXGroup;
76 | children = (
77 | 67D3DF48EF3F1662CA1280CB /* Pods_Runner.framework */,
78 | );
79 | name = Frameworks;
80 | sourceTree = "";
81 | };
82 | 9740EEB11CF90186004384FC /* Flutter */ = {
83 | isa = PBXGroup;
84 | children = (
85 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
86 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
87 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
88 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
89 | );
90 | name = Flutter;
91 | sourceTree = "";
92 | };
93 | 97C146E51CF9000F007C117D = {
94 | isa = PBXGroup;
95 | children = (
96 | 9740EEB11CF90186004384FC /* Flutter */,
97 | 97C146F01CF9000F007C117D /* Runner */,
98 | 97C146EF1CF9000F007C117D /* Products */,
99 | 03BD3683861262A284DE8696 /* Pods */,
100 | 5A3A443C3765CAFB65484AC2 /* Frameworks */,
101 | );
102 | sourceTree = "";
103 | };
104 | 97C146EF1CF9000F007C117D /* Products */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 97C146EE1CF9000F007C117D /* Runner.app */,
108 | );
109 | name = Products;
110 | sourceTree = "";
111 | };
112 | 97C146F01CF9000F007C117D /* Runner */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
116 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
117 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
118 | 97C147021CF9000F007C117D /* Info.plist */,
119 | 97C146F11CF9000F007C117D /* Supporting Files */,
120 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
121 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
122 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
123 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
124 | );
125 | path = Runner;
126 | sourceTree = "";
127 | };
128 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
129 | isa = PBXGroup;
130 | children = (
131 | );
132 | name = "Supporting Files";
133 | sourceTree = "";
134 | };
135 | /* End PBXGroup section */
136 |
137 | /* Begin PBXNativeTarget section */
138 | 97C146ED1CF9000F007C117D /* Runner */ = {
139 | isa = PBXNativeTarget;
140 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
141 | buildPhases = (
142 | 74B9E752CED3107ACE1353A2 /* [CP] Check Pods Manifest.lock */,
143 | 9740EEB61CF901F6004384FC /* Run Script */,
144 | 97C146EA1CF9000F007C117D /* Sources */,
145 | 97C146EB1CF9000F007C117D /* Frameworks */,
146 | 97C146EC1CF9000F007C117D /* Resources */,
147 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
148 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
149 | F76BE2249A09F39A13D14914 /* [CP] Embed Pods Frameworks */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = Runner;
156 | productName = Runner;
157 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
158 | productType = "com.apple.product-type.application";
159 | };
160 | /* End PBXNativeTarget section */
161 |
162 | /* Begin PBXProject section */
163 | 97C146E61CF9000F007C117D /* Project object */ = {
164 | isa = PBXProject;
165 | attributes = {
166 | LastUpgradeCheck = 1020;
167 | ORGANIZATIONNAME = "";
168 | TargetAttributes = {
169 | 97C146ED1CF9000F007C117D = {
170 | CreatedOnToolsVersion = 7.3.1;
171 | LastSwiftMigration = 1100;
172 | };
173 | };
174 | };
175 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
176 | compatibilityVersion = "Xcode 9.3";
177 | developmentRegion = en;
178 | hasScannedForEncodings = 0;
179 | knownRegions = (
180 | en,
181 | Base,
182 | );
183 | mainGroup = 97C146E51CF9000F007C117D;
184 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
185 | projectDirPath = "";
186 | projectRoot = "";
187 | targets = (
188 | 97C146ED1CF9000F007C117D /* Runner */,
189 | );
190 | };
191 | /* End PBXProject section */
192 |
193 | /* Begin PBXResourcesBuildPhase section */
194 | 97C146EC1CF9000F007C117D /* Resources */ = {
195 | isa = PBXResourcesBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
199 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
200 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
201 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
202 | );
203 | runOnlyForDeploymentPostprocessing = 0;
204 | };
205 | /* End PBXResourcesBuildPhase section */
206 |
207 | /* Begin PBXShellScriptBuildPhase section */
208 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
209 | isa = PBXShellScriptBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | );
213 | inputPaths = (
214 | );
215 | name = "Thin Binary";
216 | outputPaths = (
217 | );
218 | runOnlyForDeploymentPostprocessing = 0;
219 | shellPath = /bin/sh;
220 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
221 | };
222 | 74B9E752CED3107ACE1353A2 /* [CP] Check Pods Manifest.lock */ = {
223 | isa = PBXShellScriptBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | );
227 | inputFileListPaths = (
228 | );
229 | inputPaths = (
230 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
231 | "${PODS_ROOT}/Manifest.lock",
232 | );
233 | name = "[CP] Check Pods Manifest.lock";
234 | outputFileListPaths = (
235 | );
236 | outputPaths = (
237 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
238 | );
239 | runOnlyForDeploymentPostprocessing = 0;
240 | shellPath = /bin/sh;
241 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
242 | showEnvVarsInLog = 0;
243 | };
244 | 9740EEB61CF901F6004384FC /* Run Script */ = {
245 | isa = PBXShellScriptBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | );
249 | inputPaths = (
250 | );
251 | name = "Run Script";
252 | outputPaths = (
253 | );
254 | runOnlyForDeploymentPostprocessing = 0;
255 | shellPath = /bin/sh;
256 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
257 | };
258 | F76BE2249A09F39A13D14914 /* [CP] Embed Pods Frameworks */ = {
259 | isa = PBXShellScriptBuildPhase;
260 | buildActionMask = 2147483647;
261 | files = (
262 | );
263 | inputFileListPaths = (
264 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
265 | );
266 | name = "[CP] Embed Pods Frameworks";
267 | outputFileListPaths = (
268 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
269 | );
270 | runOnlyForDeploymentPostprocessing = 0;
271 | shellPath = /bin/sh;
272 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
273 | showEnvVarsInLog = 0;
274 | };
275 | /* End PBXShellScriptBuildPhase section */
276 |
277 | /* Begin PBXSourcesBuildPhase section */
278 | 97C146EA1CF9000F007C117D /* Sources */ = {
279 | isa = PBXSourcesBuildPhase;
280 | buildActionMask = 2147483647;
281 | files = (
282 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
283 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
284 | );
285 | runOnlyForDeploymentPostprocessing = 0;
286 | };
287 | /* End PBXSourcesBuildPhase section */
288 |
289 | /* Begin PBXVariantGroup section */
290 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
291 | isa = PBXVariantGroup;
292 | children = (
293 | 97C146FB1CF9000F007C117D /* Base */,
294 | );
295 | name = Main.storyboard;
296 | sourceTree = "";
297 | };
298 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
299 | isa = PBXVariantGroup;
300 | children = (
301 | 97C147001CF9000F007C117D /* Base */,
302 | );
303 | name = LaunchScreen.storyboard;
304 | sourceTree = "";
305 | };
306 | /* End PBXVariantGroup section */
307 |
308 | /* Begin XCBuildConfiguration section */
309 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
310 | isa = XCBuildConfiguration;
311 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
312 | buildSettings = {
313 | ALWAYS_SEARCH_USER_PATHS = NO;
314 | CLANG_ANALYZER_NONNULL = YES;
315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
316 | CLANG_CXX_LIBRARY = "libc++";
317 | CLANG_ENABLE_MODULES = YES;
318 | CLANG_ENABLE_OBJC_ARC = YES;
319 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
320 | CLANG_WARN_BOOL_CONVERSION = YES;
321 | CLANG_WARN_COMMA = YES;
322 | CLANG_WARN_CONSTANT_CONVERSION = YES;
323 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
325 | CLANG_WARN_EMPTY_BODY = YES;
326 | CLANG_WARN_ENUM_CONVERSION = YES;
327 | CLANG_WARN_INFINITE_RECURSION = YES;
328 | CLANG_WARN_INT_CONVERSION = YES;
329 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
330 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
331 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
333 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
334 | CLANG_WARN_STRICT_PROTOTYPES = YES;
335 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
336 | CLANG_WARN_UNREACHABLE_CODE = YES;
337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
339 | COPY_PHASE_STRIP = NO;
340 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
341 | ENABLE_NS_ASSERTIONS = NO;
342 | ENABLE_STRICT_OBJC_MSGSEND = YES;
343 | GCC_C_LANGUAGE_STANDARD = gnu99;
344 | GCC_NO_COMMON_BLOCKS = YES;
345 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
346 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
347 | GCC_WARN_UNDECLARED_SELECTOR = YES;
348 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
349 | GCC_WARN_UNUSED_FUNCTION = YES;
350 | GCC_WARN_UNUSED_VARIABLE = YES;
351 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
352 | MTL_ENABLE_DEBUG_INFO = NO;
353 | SDKROOT = iphoneos;
354 | SUPPORTED_PLATFORMS = iphoneos;
355 | TARGETED_DEVICE_FAMILY = "1,2";
356 | VALIDATE_PRODUCT = YES;
357 | };
358 | name = Profile;
359 | };
360 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
361 | isa = XCBuildConfiguration;
362 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
363 | buildSettings = {
364 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
365 | CLANG_ENABLE_MODULES = YES;
366 | CODE_SIGN_IDENTITY = "Apple Development";
367 | CODE_SIGN_STYLE = Automatic;
368 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
369 | DEVELOPMENT_TEAM = 6V285R83MQ;
370 | ENABLE_BITCODE = NO;
371 | FRAMEWORK_SEARCH_PATHS = (
372 | "$(inherited)",
373 | "$(PROJECT_DIR)/Flutter",
374 | );
375 | INFOPLIST_FILE = Runner/Info.plist;
376 | LD_RUNPATH_SEARCH_PATHS = (
377 | "$(inherited)",
378 | "@executable_path/Frameworks",
379 | );
380 | LIBRARY_SEARCH_PATHS = (
381 | "$(inherited)",
382 | "$(PROJECT_DIR)/Flutter",
383 | );
384 | PRODUCT_BUNDLE_IDENTIFIER = "com.example.simple-map";
385 | PRODUCT_NAME = "$(TARGET_NAME)";
386 | PROVISIONING_PROFILE_SPECIFIER = "";
387 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
388 | SWIFT_VERSION = 5.0;
389 | VERSIONING_SYSTEM = "apple-generic";
390 | };
391 | name = Profile;
392 | };
393 | 97C147031CF9000F007C117D /* Debug */ = {
394 | isa = XCBuildConfiguration;
395 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
396 | buildSettings = {
397 | ALWAYS_SEARCH_USER_PATHS = NO;
398 | CLANG_ANALYZER_NONNULL = YES;
399 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
400 | CLANG_CXX_LIBRARY = "libc++";
401 | CLANG_ENABLE_MODULES = YES;
402 | CLANG_ENABLE_OBJC_ARC = YES;
403 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
404 | CLANG_WARN_BOOL_CONVERSION = YES;
405 | CLANG_WARN_COMMA = YES;
406 | CLANG_WARN_CONSTANT_CONVERSION = YES;
407 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
408 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
409 | CLANG_WARN_EMPTY_BODY = YES;
410 | CLANG_WARN_ENUM_CONVERSION = YES;
411 | CLANG_WARN_INFINITE_RECURSION = YES;
412 | CLANG_WARN_INT_CONVERSION = YES;
413 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
414 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
415 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
417 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
418 | CLANG_WARN_STRICT_PROTOTYPES = YES;
419 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
420 | CLANG_WARN_UNREACHABLE_CODE = YES;
421 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
422 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
423 | COPY_PHASE_STRIP = NO;
424 | DEBUG_INFORMATION_FORMAT = dwarf;
425 | ENABLE_STRICT_OBJC_MSGSEND = YES;
426 | ENABLE_TESTABILITY = YES;
427 | GCC_C_LANGUAGE_STANDARD = gnu99;
428 | GCC_DYNAMIC_NO_PIC = NO;
429 | GCC_NO_COMMON_BLOCKS = YES;
430 | GCC_OPTIMIZATION_LEVEL = 0;
431 | GCC_PREPROCESSOR_DEFINITIONS = (
432 | "DEBUG=1",
433 | "$(inherited)",
434 | );
435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
437 | GCC_WARN_UNDECLARED_SELECTOR = YES;
438 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
439 | GCC_WARN_UNUSED_FUNCTION = YES;
440 | GCC_WARN_UNUSED_VARIABLE = YES;
441 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
442 | MTL_ENABLE_DEBUG_INFO = YES;
443 | ONLY_ACTIVE_ARCH = YES;
444 | SDKROOT = iphoneos;
445 | TARGETED_DEVICE_FAMILY = "1,2";
446 | };
447 | name = Debug;
448 | };
449 | 97C147041CF9000F007C117D /* Release */ = {
450 | isa = XCBuildConfiguration;
451 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
452 | buildSettings = {
453 | ALWAYS_SEARCH_USER_PATHS = NO;
454 | CLANG_ANALYZER_NONNULL = YES;
455 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
456 | CLANG_CXX_LIBRARY = "libc++";
457 | CLANG_ENABLE_MODULES = YES;
458 | CLANG_ENABLE_OBJC_ARC = YES;
459 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
460 | CLANG_WARN_BOOL_CONVERSION = YES;
461 | CLANG_WARN_COMMA = YES;
462 | CLANG_WARN_CONSTANT_CONVERSION = YES;
463 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
464 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
465 | CLANG_WARN_EMPTY_BODY = YES;
466 | CLANG_WARN_ENUM_CONVERSION = YES;
467 | CLANG_WARN_INFINITE_RECURSION = YES;
468 | CLANG_WARN_INT_CONVERSION = YES;
469 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
470 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
471 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
472 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
473 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
474 | CLANG_WARN_STRICT_PROTOTYPES = YES;
475 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
476 | CLANG_WARN_UNREACHABLE_CODE = YES;
477 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
478 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
479 | COPY_PHASE_STRIP = NO;
480 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
481 | ENABLE_NS_ASSERTIONS = NO;
482 | ENABLE_STRICT_OBJC_MSGSEND = YES;
483 | GCC_C_LANGUAGE_STANDARD = gnu99;
484 | GCC_NO_COMMON_BLOCKS = YES;
485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
486 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
487 | GCC_WARN_UNDECLARED_SELECTOR = YES;
488 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
489 | GCC_WARN_UNUSED_FUNCTION = YES;
490 | GCC_WARN_UNUSED_VARIABLE = YES;
491 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
492 | MTL_ENABLE_DEBUG_INFO = NO;
493 | SDKROOT = iphoneos;
494 | SUPPORTED_PLATFORMS = iphoneos;
495 | SWIFT_COMPILATION_MODE = wholemodule;
496 | SWIFT_OPTIMIZATION_LEVEL = "-O";
497 | TARGETED_DEVICE_FAMILY = "1,2";
498 | VALIDATE_PRODUCT = YES;
499 | };
500 | name = Release;
501 | };
502 | 97C147061CF9000F007C117D /* Debug */ = {
503 | isa = XCBuildConfiguration;
504 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
505 | buildSettings = {
506 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
507 | CLANG_ENABLE_MODULES = YES;
508 | CODE_SIGN_IDENTITY = "Apple Development";
509 | CODE_SIGN_STYLE = Automatic;
510 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
511 | DEVELOPMENT_TEAM = 6V285R83MQ;
512 | ENABLE_BITCODE = NO;
513 | FRAMEWORK_SEARCH_PATHS = (
514 | "$(inherited)",
515 | "$(PROJECT_DIR)/Flutter",
516 | );
517 | INFOPLIST_FILE = Runner/Info.plist;
518 | LD_RUNPATH_SEARCH_PATHS = (
519 | "$(inherited)",
520 | "@executable_path/Frameworks",
521 | );
522 | LIBRARY_SEARCH_PATHS = (
523 | "$(inherited)",
524 | "$(PROJECT_DIR)/Flutter",
525 | );
526 | PRODUCT_BUNDLE_IDENTIFIER = "com.example.simple-map";
527 | PRODUCT_NAME = "$(TARGET_NAME)";
528 | PROVISIONING_PROFILE_SPECIFIER = "";
529 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
530 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
531 | SWIFT_VERSION = 5.0;
532 | VERSIONING_SYSTEM = "apple-generic";
533 | };
534 | name = Debug;
535 | };
536 | 97C147071CF9000F007C117D /* Release */ = {
537 | isa = XCBuildConfiguration;
538 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
539 | buildSettings = {
540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
541 | CLANG_ENABLE_MODULES = YES;
542 | CODE_SIGN_IDENTITY = "Apple Development";
543 | CODE_SIGN_STYLE = Automatic;
544 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
545 | DEVELOPMENT_TEAM = 6V285R83MQ;
546 | ENABLE_BITCODE = NO;
547 | FRAMEWORK_SEARCH_PATHS = (
548 | "$(inherited)",
549 | "$(PROJECT_DIR)/Flutter",
550 | );
551 | INFOPLIST_FILE = Runner/Info.plist;
552 | LD_RUNPATH_SEARCH_PATHS = (
553 | "$(inherited)",
554 | "@executable_path/Frameworks",
555 | );
556 | LIBRARY_SEARCH_PATHS = (
557 | "$(inherited)",
558 | "$(PROJECT_DIR)/Flutter",
559 | );
560 | PRODUCT_BUNDLE_IDENTIFIER = "com.example.simple-map";
561 | PRODUCT_NAME = "$(TARGET_NAME)";
562 | PROVISIONING_PROFILE_SPECIFIER = "";
563 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
564 | SWIFT_VERSION = 5.0;
565 | VERSIONING_SYSTEM = "apple-generic";
566 | };
567 | name = Release;
568 | };
569 | /* End XCBuildConfiguration section */
570 |
571 | /* Begin XCConfigurationList section */
572 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
573 | isa = XCConfigurationList;
574 | buildConfigurations = (
575 | 97C147031CF9000F007C117D /* Debug */,
576 | 97C147041CF9000F007C117D /* Release */,
577 | 249021D3217E4FDB00AE95B9 /* Profile */,
578 | );
579 | defaultConfigurationIsVisible = 0;
580 | defaultConfigurationName = Release;
581 | };
582 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
583 | isa = XCConfigurationList;
584 | buildConfigurations = (
585 | 97C147061CF9000F007C117D /* Debug */,
586 | 97C147071CF9000F007C117D /* Release */,
587 | 249021D4217E4FDB00AE95B9 /* Profile */,
588 | );
589 | defaultConfigurationIsVisible = 0;
590 | defaultConfigurationName = Release;
591 | };
592 | /* End XCConfigurationList section */
593 | };
594 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
595 | }
596 |
--------------------------------------------------------------------------------