├── 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 | [![Build Status](https://github.com/tiamo/flutter-simple-map/actions/workflows/ci.yml/badge.svg)](https://github.com/tiamo/flutter-simple-map) 7 | [![Pub package](https://img.shields.io/pub/v/simple_map.svg)](https://pub.dartlang.org/packages/simple_map) 8 | [![Star on GitHub](https://img.shields.io/github/stars/tiamo/flutter-simple-map.svg?style=flat&logo=github&colorB=deeppink&label=stars)](https://github.com/tiamo/flutter-simple-map) 9 | [![License: MIT](https://img.shields.io/badge/license-MIT-purple.svg)](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 | [![License: MIT](https://img.shields.io/badge/license-MIT-purple.svg)](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 | --------------------------------------------------------------------------------