├── .gitignore
├── .pubignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
└── debugger_v1.png
├── example
├── .gitignore
├── .metadata
├── README.md
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── example
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── 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
│ │ │ │ ├── values-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── assets
│ ├── brazil_counties.json
│ ├── level.geojson
│ ├── polygons.json
│ ├── rooms.geojson
│ ├── south_america.json
│ └── workplaces.geojson
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── 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-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
├── lib
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml
└── web
│ ├── favicon.png
│ ├── icons
│ ├── Icon-192.png
│ └── Icon-512.png
│ ├── index.html
│ └── manifest.json
├── lib
├── src
│ ├── addon
│ │ ├── legend
│ │ │ ├── gradient_legend.dart
│ │ │ └── legend.dart
│ │ └── map_addon.dart
│ ├── data
│ │ ├── geometries.dart
│ │ ├── map_data_source.dart
│ │ ├── map_feature.dart
│ │ ├── map_layer.dart
│ │ ├── property_limits.dart
│ │ └── simplified_path.dart
│ ├── data_reader.dart
│ ├── debugger.dart
│ ├── draw_utils.dart
│ ├── drawable
│ │ ├── circle_marker.dart
│ │ ├── drawable.dart
│ │ ├── drawable_builder.dart
│ │ ├── drawable_feature.dart
│ │ ├── drawable_layer.dart
│ │ ├── drawable_layer_chunk.dart
│ │ ├── drawable_line.dart
│ │ ├── drawable_path.dart
│ │ ├── drawable_polygon.dart
│ │ └── marker.dart
│ ├── error.dart
│ ├── low_quality_mode.dart
│ ├── map_highlight.dart
│ ├── map_painter.dart
│ ├── simplifier.dart
│ ├── theme
│ │ ├── map_gradient_theme.dart
│ │ ├── map_highlight_theme.dart
│ │ ├── map_rule_theme.dart
│ │ ├── map_theme.dart
│ │ └── map_value_theme.dart
│ ├── vector_map.dart
│ ├── vector_map_api.dart
│ ├── vector_map_controller.dart
│ └── vector_map_mode.dart
└── vector_map.dart
├── pubspec.lock
└── pubspec.yaml
/.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 | # Android related
34 | **/android/**/gradle-wrapper.jar
35 | **/android/.gradle
36 | **/android/captures/
37 | **/android/gradlew
38 | **/android/gradlew.bat
39 | **/android/local.properties
40 | **/android/**/GeneratedPluginRegistrant.java
41 |
42 | # iOS/XCode related
43 | **/ios/**/*.mode1v3
44 | **/ios/**/*.mode2v3
45 | **/ios/**/*.moved-aside
46 | **/ios/**/*.pbxuser
47 | **/ios/**/*.perspectivev3
48 | **/ios/**/*sync/
49 | **/ios/**/.sconsign.dblite
50 | **/ios/**/.tags*
51 | **/ios/**/.vagrant/
52 | **/ios/**/DerivedData/
53 | **/ios/**/Icon?
54 | **/ios/**/Pods/
55 | **/ios/**/.symlinks/
56 | **/ios/**/profile
57 | **/ios/**/xcuserdata
58 | **/ios/.generated/
59 | **/ios/Flutter/App.framework
60 | **/ios/Flutter/Flutter.framework
61 | **/ios/Flutter/Flutter.podspec
62 | **/ios/Flutter/Generated.xcconfig
63 | **/ios/Flutter/app.flx
64 | **/ios/Flutter/app.zip
65 | **/ios/Flutter/flutter_assets/
66 | **/ios/Flutter/flutter_export_environment.sh
67 | **/ios/ServiceDefinitions.json
68 | **/ios/Runner/GeneratedPluginRegistrant.*
69 |
70 | # Exceptions to above rules.
71 | !**/ios/**/default.mode1v3
72 | !**/ios/**/default.mode2v3
73 | !**/ios/**/default.pbxuser
74 | !**/ios/**/default.perspectivev3
75 |
--------------------------------------------------------------------------------
/.pubignore:
--------------------------------------------------------------------------------
1 | docs/
2 |
3 | # Miscellaneous
4 | *.class
5 | *.log
6 | *.pyc
7 | *.swp
8 | .DS_Store
9 | .atom/
10 | .buildlog/
11 | .history
12 | .svn/
13 |
14 | # IntelliJ related
15 | *.iml
16 | *.ipr
17 | *.iws
18 | .idea/
19 |
20 | # The .vscode folder contains launch configuration and tasks you configure in
21 | # VS Code which you may wish to be included in version control, so this line
22 | # is commented out by default.
23 | #.vscode/
24 |
25 | # Flutter/Dart/Pub related
26 | **/doc/api/
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | build/
34 |
35 | # Android related
36 | **/android/**/gradle-wrapper.jar
37 | **/android/.gradle
38 | **/android/captures/
39 | **/android/gradlew
40 | **/android/gradlew.bat
41 | **/android/local.properties
42 | **/android/**/GeneratedPluginRegistrant.java
43 |
44 | # iOS/XCode related
45 | **/ios/**/*.mode1v3
46 | **/ios/**/*.mode2v3
47 | **/ios/**/*.moved-aside
48 | **/ios/**/*.pbxuser
49 | **/ios/**/*.perspectivev3
50 | **/ios/**/*sync/
51 | **/ios/**/.sconsign.dblite
52 | **/ios/**/.tags*
53 | **/ios/**/.vagrant/
54 | **/ios/**/DerivedData/
55 | **/ios/**/Icon?
56 | **/ios/**/Pods/
57 | **/ios/**/.symlinks/
58 | **/ios/**/profile
59 | **/ios/**/xcuserdata
60 | **/ios/.generated/
61 | **/ios/Flutter/App.framework
62 | **/ios/Flutter/Flutter.framework
63 | **/ios/Flutter/Flutter.podspec
64 | **/ios/Flutter/Generated.xcconfig
65 | **/ios/Flutter/app.flx
66 | **/ios/Flutter/app.zip
67 | **/ios/Flutter/flutter_assets/
68 | **/ios/Flutter/flutter_export_environment.sh
69 | **/ios/ServiceDefinitions.json
70 | **/ios/Runner/GeneratedPluginRegistrant.*
71 |
72 | # Exceptions to above rules.
73 | !**/ios/**/default.mode1v3
74 | !**/ios/**/default.mode2v3
75 | !**/ios/**/default.pbxuser
76 | !**/ios/**/default.perspectivev3
77 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.7.0
2 |
3 | * Multiline reader
4 |
5 | ## 0.6.1+2
6 |
7 | * Updating the README
8 |
9 | ## 0.6.1+1
10 |
11 | * Removing unnecessary imports
12 |
13 | ## 0.6.1
14 |
15 | * Bugfix mobile
16 | * Wrong feature on click listener
17 |
18 | ## 0.6.0
19 |
20 | * Pan and zoom mode
21 | * Placeholder for map without layers
22 | * `MapDataSource.geoJSON` renamed to `MapDataSource.geoJson`
23 | * `contourThickness` parameter moved from `VectorMap` to `VectorMapController`
24 | * `VectorMapController.getLayer` renamed to `VectorMapController.getLayerByIndex`
25 | * New methods
26 | * `VectorMapController.getLayerById`
27 | * `VectorMapController.hasLayerId`
28 |
29 | ## 0.5.0
30 |
31 | * Gradient legend
32 | * `MapLayer.hoverTheme` refactored to `MapLayer.highlightTheme` to be used by addons as well
33 |
34 | ## 0.4.0
35 |
36 | * Debugger
37 | * GeoJSON line geometry reader
38 | * It remains to calculate buffered area to allow the hover to be detected
39 | * Experimental (the API will change)
40 | * Addons
41 | * Gradient legend
42 |
43 | ## 0.3.0
44 |
45 | * Drastic reduction in package size
46 | * Demo moved to separate repository
47 | * Marker
48 |
49 | ## 0.2.0
50 |
51 | * Multiple layers
52 | * GeoJSON point geometry reader
53 |
54 | ## 0.1.0
55 |
56 | * Initial release
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Carlos Eduardo Leite de Andrade
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.
22 |
--------------------------------------------------------------------------------
/docs/debugger_v1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/docs/debugger_v1.png
--------------------------------------------------------------------------------
/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 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: b1395592de68cc8ac4522094ae59956dd21a91db
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # 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/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/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 30
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | defaultConfig {
36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
37 | applicationId "com.example.example"
38 | minSdkVersion 16
39 | targetSdkVersion 30
40 | versionCode flutterVersionCode.toInteger()
41 | versionName flutterVersionName
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
59 | }
60 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
13 |
17 |
21 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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:4.1.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 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/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-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/example/assets/polygons.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "properties": {
7 | "Seq": 1,
8 | "Name": "Einstein",
9 | "Rnd": "73",
10 | "Gts": 15000
11 | },
12 | "geometry": {
13 | "type": "Polygon",
14 | "coordinates": [
15 | [
16 | [
17 | 1,
18 | 5
19 | ],
20 | [
21 | 2,
22 | 4
23 | ],
24 | [
25 | 1,
26 | 3
27 | ],
28 | [
29 | 0,
30 | 4
31 | ],
32 | [
33 | 1,
34 | 5
35 | ]
36 | ]
37 | ]
38 | }
39 | },
40 | {
41 | "type": "Feature",
42 | "properties": {
43 | "Seq": 2,
44 | "Name": "Newton",
45 | "Rnd": "92",
46 | "Gts": 7500
47 | },
48 | "geometry": {
49 | "type": "Polygon",
50 | "coordinates": [
51 | [
52 | [
53 | 2,
54 | 0
55 | ],
56 | [
57 | 0,
58 | 2
59 | ],
60 | [
61 | 2,
62 | 4
63 | ],
64 | [
65 | 4,
66 | 2
67 | ],
68 | [
69 | 2,
70 | 0
71 | ]
72 | ]
73 | ]
74 | }
75 | },
76 | {
77 | "type": "Feature",
78 | "properties": {
79 | "Seq": 3,
80 | "Name": "Galileu",
81 | "Rnd": "10",
82 | "Gts": 3000
83 | },
84 | "geometry": {
85 | "type": "Polygon",
86 | "coordinates": [
87 | [
88 | [
89 | 2,
90 | 6
91 | ],
92 | [
93 | 3,
94 | 5
95 | ],
96 | [
97 | 2,
98 | 4
99 | ],
100 | [
101 | 1,
102 | 5
103 | ],
104 | [
105 | 2,
106 | 6
107 | ]
108 | ]
109 | ]
110 | }
111 | },
112 | {
113 | "type": "Feature",
114 | "properties": {
115 | "Seq": 4,
116 | "Name": "Darwin",
117 | "Gts": 15000
118 | },
119 | "geometry": {
120 | "type": "Polygon",
121 | "coordinates": [
122 | [
123 | [
124 | 4,
125 | 2
126 | ],
127 | [
128 | 2,
129 | 4
130 | ],
131 | [
132 | 4,
133 | 6
134 | ],
135 | [
136 | 6,
137 | 4
138 | ],
139 | [
140 | 4,
141 | 2
142 | ]
143 | ]
144 | ]
145 | }
146 | },
147 | {
148 | "type": "Feature",
149 | "properties": {
150 | "Seq": 5,
151 | "Name": "Pasteur",
152 | "Rnd": "77",
153 | "Gts": 17000
154 | },
155 | "geometry": {
156 | "type": "Polygon",
157 | "coordinates": [
158 | [
159 | [
160 | 4,
161 | 2
162 | ],
163 | [
164 | 5,
165 | 1
166 | ],
167 | [
168 | 4,
169 | 0
170 | ],
171 | [
172 | 3,
173 | 1
174 | ],
175 | [
176 | 4,
177 | 2
178 | ]
179 | ]
180 | ]
181 | }
182 | },
183 | {
184 | "type": "Feature",
185 | "properties": {
186 | "Seq": 6,
187 | "Name": "Faraday",
188 | "Rnd": "32",
189 | "Gts": 17500
190 | },
191 | "geometry": {
192 | "type": "Polygon",
193 | "coordinates": [
194 | [
195 | [
196 | 6,
197 | 0
198 | ],
199 | [
200 | 4,
201 | 2
202 | ],
203 | [
204 | 8,
205 | 6
206 | ],
207 | [
208 | 10,
209 | 4
210 | ],
211 | [
212 | 6,
213 | 0
214 | ]
215 | ]
216 | ]
217 | }
218 | },
219 | {
220 | "type": "Feature",
221 | "properties": {
222 | "Seq": 7,
223 | "Name": "Arquimedes",
224 | "Rnd": "87",
225 | "Gts": 25000
226 | },
227 | "geometry": {
228 | "type": "Polygon",
229 | "coordinates": [
230 | [
231 | [
232 | 6,
233 | 6
234 | ],
235 | [
236 | 7,
237 | 5
238 | ],
239 | [
240 | 6,
241 | 4
242 | ],
243 | [
244 | 5,
245 | 5
246 | ],
247 | [
248 | 6,
249 | 6
250 | ]
251 | ]
252 | ]
253 | }
254 | },
255 | {
256 | "type": "Feature",
257 | "properties": {
258 | "Seq": 8,
259 | "Name": "Tesla",
260 | "Rnd": "17",
261 | "Gts": 12500
262 | },
263 | "geometry": {
264 | "type": "Polygon",
265 | "coordinates": [
266 | [
267 | [
268 | 8,
269 | 2
270 | ],
271 | [
272 | 9,
273 | 1
274 | ],
275 | [
276 | 8,
277 | 0
278 | ],
279 | [
280 | 7,
281 | 1
282 | ],
283 | [
284 | 8,
285 | 2
286 | ]
287 | ]
288 | ]
289 | }
290 | },
291 | {
292 | "type": "Feature",
293 | "properties": {
294 | "Seq": 9,
295 | "Name": "Lavoisier",
296 | "Gts": 4000
297 | },
298 | "geometry": {
299 | "type": "Polygon",
300 | "coordinates": [
301 | [
302 | [
303 | 10,
304 | 0
305 | ],
306 | [
307 | 8,
308 | 2
309 | ],
310 | [
311 | 10,
312 | 4
313 | ],
314 | [
315 | 12,
316 | 2
317 | ],
318 | [
319 | 10,
320 | 0
321 | ]
322 | ]
323 | ]
324 | }
325 | },
326 | {
327 | "type": "Feature",
328 | "properties": {
329 | "Seq": 10,
330 | "Name": "Kepler",
331 | "Rnd": "32",
332 | "Gts": 18000
333 | },
334 | "geometry": {
335 | "type": "Polygon",
336 | "coordinates": [
337 | [
338 | [
339 | 10,
340 | 6
341 | ],
342 | [
343 | 11,
344 | 5
345 | ],
346 | [
347 | 10,
348 | 4
349 | ],
350 | [
351 | 9,
352 | 5
353 | ],
354 | [
355 | 10,
356 | 6
357 | ]
358 | ]
359 | ]
360 | }
361 | },
362 | {
363 | "type": "Feature",
364 | "properties": {
365 | "Seq": 11,
366 | "Name": "Turing",
367 | "Rnd": "93",
368 | "Gts": 31400
369 | },
370 | "geometry": {
371 | "type": "Polygon",
372 | "coordinates": [
373 | [
374 | [
375 | 11,
376 | 5
377 | ],
378 | [
379 | 12,
380 | 4
381 | ],
382 | [
383 | 11,
384 | 3
385 | ],
386 | [
387 | 10,
388 | 4
389 | ],
390 | [
391 | 11,
392 | 5
393 | ]
394 | ]
395 | ]
396 | }
397 | }
398 | ]
399 | }
--------------------------------------------------------------------------------
/example/assets/rooms.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "name": "rooms",
4 | "features": [
5 | {
6 | "type": "Feature",
7 | "properties": {
8 | "_id": "LUUID(\"b46f97a8-6827-6e43-8957-a73d4c67641b\")",
9 | "FeatureId": "LUUID(\"a4183b99-3c7a-c746-a158-ed57556582ae\")"
10 | },
11 | "geometry": {
12 | "type": "MultiPolygon",
13 | "coordinates": [
14 | [
15 | [
16 | [
17 | 12.9316,
18 | 9.89333
19 | ],
20 | [
21 | 11.1673,
22 | 9.89333
23 | ],
24 | [
25 | 11.1673,
26 | 12.7614
27 | ],
28 | [
29 | 11.1673,
30 | 12.7614
31 | ],
32 | [
33 | 11.1673,
34 | 14.0811
35 | ],
36 | [
37 | 12.9315548074708,
38 | 14.0811
39 | ],
40 | [
41 | 12.9316,
42 | 9.89333
43 | ]
44 | ]
45 | ]
46 | ]
47 | }
48 | },
49 | {
50 | "type": "Feature",
51 | "properties": {
52 | "_id": "LUUID(\"abd9b8d9-9bae-3c48-acd4-598568126703\")",
53 | "FeatureId": "LUUID(\"245ae597-5917-ab4f-a5b7-2abf9b687b51\")"
54 | },
55 | "geometry": {
56 | "type": "MultiPolygon",
57 | "coordinates": [
58 | [
59 | [
60 | [
61 | 12.9315,
62 | 19.1585
63 | ],
64 | [
65 | 12.5008,
66 | 19.1585
67 | ],
68 | [
69 | 12.5008,
70 | 19.1358
71 | ],
72 | [
73 | 12.4685,
74 | 19.1358
75 | ],
76 | [
77 | 12.4685,
78 | 19.1358
79 | ],
80 | [
81 | 12.4685,
82 | 19.2038
83 | ],
84 | [
85 | 12.4685,
86 | 19.2038
87 | ],
88 | [
89 | 12.4685,
90 | 19.2038
91 | ],
92 | [
93 | 11.5165,
94 | 19.2038
95 | ],
96 | [
97 | 11.5165,
98 | 19.2038
99 | ],
100 | [
101 | 11.5165,
102 | 19.2038
103 | ],
104 | [
105 | 11.5165,
106 | 19.2038
107 | ],
108 | [
109 | 11.5165,
110 | 19.2038
111 | ],
112 | [
113 | 11.5165,
114 | 19.2038
115 | ],
116 | [
117 | 11.5165,
118 | 19.136
119 | ],
120 | [
121 | 11.5165,
122 | 19.136
123 | ],
124 | [
125 | 11.485,
126 | 19.136
127 | ],
128 | [
129 | 11.485,
130 | 19.136
131 | ],
132 | [
133 | 11.4843,
134 | 19.1585
135 | ],
136 | [
137 | 11.4843,
138 | 19.1585
139 | ],
140 | [
141 | 10.213,
142 | 19.1585
143 | ],
144 | [
145 | 10.213,
146 | 17.9874
147 | ],
148 | [
149 | 11.1673,
150 | 17.9874
151 | ],
152 | [
153 | 11.1673,
154 | 14.0929
155 | ],
156 | [
157 | 12.9315,
158 | 14.0929
159 | ],
160 | [
161 | 12.9315,
162 | 19.1585
163 | ]
164 | ]
165 | ]
166 | ]
167 | }
168 | },
169 | {
170 | "type": "Feature",
171 | "properties": {
172 | "_id": "LUUID(\"b8ba6975-a436-e546-9251-9202ffaf4a03\")",
173 | "FeatureId": "LUUID(\"c7dd7f42-4dec-8442-a0ce-e13ac0b7021a\")"
174 | },
175 | "geometry": {
176 | "type": "MultiPolygon",
177 | "coordinates": [
178 | [
179 | [
180 | [
181 | 16.3897,
182 | 17.9442
183 | ],
184 | [
185 | 16.3897,
186 | 19.1599
187 | ],
188 | [
189 | 15.2177545029263,
190 | 19.1599
191 | ],
192 | [
193 | 15.2174,
194 | 19.136
195 | ],
196 | [
197 | 15.185,
198 | 19.1353
199 | ],
200 | [
201 | 15.185,
202 | 19.2033
203 | ],
204 | [
205 | 15.185,
206 | 19.2033
207 | ],
208 | [
209 | 14.2331,
210 | 19.2033
211 | ],
212 | [
213 | 14.2331,
214 | 19.2033
215 | ],
216 | [
217 | 14.2331,
218 | 19.1521887937681
219 | ],
220 | [
221 | 14.2331,
222 | 19.1357835907336
223 | ],
224 | [
225 | 14.2008,
226 | 19.1358
227 | ],
228 | [
229 | 14.2008,
230 | 19.1585
231 | ],
232 | [
233 | 12.9433,
234 | 19.1585
235 | ],
236 | [
237 | 12.9434,
238 | 17.0236
239 | ],
240 | [
241 | 16.4474,
242 | 17.0236
243 | ],
244 | [
245 | 16.4474,
246 | 17.9244
247 | ],
248 | [
249 | 16.3008,
250 | 17.9244
251 | ],
252 | [
253 | 16.3008,
254 | 17.9442
255 | ],
256 | [
257 | 16.3897,
258 | 17.9442
259 | ]
260 | ]
261 | ]
262 | ]
263 | }
264 | },
265 | {
266 | "type": "Feature",
267 | "properties": {
268 | "_id": "LUUID(\"4fee597f-e995-9742-b958-739016dd69b9\")",
269 | "FeatureId": "LUUID(\"0f7d3ace-c2f3-a34e-a0ed-734f2c01681d\")"
270 | },
271 | "geometry": {
272 | "type": "MultiPolygon",
273 | "coordinates": [
274 | [
275 | [
276 | [
277 | 16.4474,
278 | 17.0117
279 | ],
280 | [
281 | 16.4474,
282 | 15.1843
283 | ],
284 | [
285 | 16.3008,
286 | 15.1843
287 | ],
288 | [
289 | 16.3008,
290 | 15.1646
291 | ],
292 | [
293 | 16.3882,
294 | 15.1646
295 | ],
296 | [
297 | 16.3882,
298 | 13.9491140476755
299 | ],
300 | [
301 | 13.6975,
302 | 13.9491140476755
303 | ],
304 | [
305 | 13.6974,
306 | 17.0117
307 | ],
308 | [
309 | 16.4474,
310 | 17.0117
311 | ]
312 | ]
313 | ]
314 | ]
315 | }
316 | }
317 | ]
318 | }
--------------------------------------------------------------------------------
/example/assets/workplaces.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "name": "workplaces",
4 | "features": [
5 | {
6 | "type": "Feature",
7 | "properties": {
8 | "_id": "LUUID(\"21eabee1-8efb-2043-b974-9ed1f658b1f7\")",
9 | "FeatureId": "LUUID(\"fece8db1-fdab-9180-350c-695608503c3d\")"
10 | },
11 | "geometry": {
12 | "type": "Point",
13 | "coordinates": [
14 | 12.2337,
15 | 18.7292
16 | ]
17 | }
18 | },
19 | {
20 | "type": "Feature",
21 | "properties": {
22 | "_id": "LUUID(\"4d40001f-dce0-bd45-9b45-8eefa83eda99\")",
23 | "FeatureId": "LUUID(\"5e510414-6776-1726-6ad7-5a532039ccd8\")"
24 | },
25 | "geometry": {
26 | "type": "Point",
27 | "coordinates": [
28 | 12.2337,
29 | 16.9062
30 | ]
31 | }
32 | },
33 | {
34 | "type": "Feature",
35 | "properties": {
36 | "_id": "LUUID(\"7785d83b-e932-5148-aa3e-b6ef351d8526\")",
37 | "FeatureId": "LUUID(\"54408dc0-d796-3b19-fbcd-9edd45d6a78c\")"
38 | },
39 | "geometry": {
40 | "type": "Point",
41 | "coordinates": [
42 | 12.2337,
43 | 17.5599
44 | ]
45 | }
46 | },
47 | {
48 | "type": "Feature",
49 | "properties": {
50 | "_id": "LUUID(\"7589175b-b9aa-014c-a50d-2aca849c9c1d\")",
51 | "FeatureId": "LUUID(\"dbc2461e-8e58-7c54-8683-c5aec0419bc1\")"
52 | },
53 | "geometry": {
54 | "type": "Point",
55 | "coordinates": [
56 | 11.7612,
57 | 16.9062
58 | ]
59 | }
60 | },
61 | {
62 | "type": "Feature",
63 | "properties": {
64 | "_id": "LUUID(\"2232a661-ea68-7b44-a256-f43ad6f9f7aa\")",
65 | "FeatureId": "LUUID(\"9e758445-a4a1-13e8-9fa9-333ee641fb16\")"
66 | },
67 | "geometry": {
68 | "type": "Point",
69 | "coordinates": [
70 | 11.7612,
71 | 15.7094
72 | ]
73 | }
74 | },
75 | {
76 | "type": "Feature",
77 | "properties": {
78 | "_id": "LUUID(\"77467e68-70b7-f54d-8dd5-a11a9563515f\")",
79 | "FeatureId": "LUUID(\"c1472bac-3f06-f598-fbaa-1175bcba8feb\")"
80 | },
81 | "geometry": {
82 | "type": "Point",
83 | "coordinates": [
84 | 11.7612,
85 | 15.056
86 | ]
87 | }
88 | },
89 | {
90 | "type": "Feature",
91 | "properties": {
92 | "_id": "LUUID(\"acfd7bbe-91cc-2e42-9777-4c67d27446a7\")",
93 | "FeatureId": "LUUID(\"8c09e269-4ea7-701b-c38a-e3f81241ebfe\")"
94 | },
95 | "geometry": {
96 | "type": "Point",
97 | "coordinates": [
98 | 11.7612,
99 | 17.5599
100 | ]
101 | }
102 | },
103 | {
104 | "type": "Feature",
105 | "properties": {
106 | "_id": "LUUID(\"8018c4f8-3bcc-1043-8911-4f91ebf8bc39\")",
107 | "FeatureId": "LUUID(\"29cb41ea-3ff8-13f0-815b-cb3be9c30ccf\")"
108 | },
109 | "geometry": {
110 | "type": "Point",
111 | "coordinates": [
112 | 11.7612,
113 | 18.7292
114 | ]
115 | }
116 | },
117 | {
118 | "type": "Feature",
119 | "properties": {
120 | "_id": "LUUID(\"885cd8af-53e9-f744-8484-6e62a1eb8645\")",
121 | "FeatureId": "LUUID(\"5eed3d5e-a461-3ec5-e3b7-3d9a0a16f87c\")"
122 | },
123 | "geometry": {
124 | "type": "Point",
125 | "coordinates": [
126 | 11.7612,
127 | 12.911
128 | ]
129 | }
130 | },
131 | {
132 | "type": "Feature",
133 | "properties": {
134 | "_id": "LUUID(\"a65cf58e-9a83-f34c-9099-a5512486879c\")",
135 | "FeatureId": "LUUID(\"a242c63f-7cd2-29fd-df33-8a6fb0c34476\")"
136 | },
137 | "geometry": {
138 | "type": "Point",
139 | "coordinates": [
140 | 11.7612,
141 | 12.2575
142 | ]
143 | }
144 | },
145 | {
146 | "type": "Feature",
147 | "properties": {
148 | "_id": "LUUID(\"061ce968-416d-924d-bd56-5e167e56bd7c\")",
149 | "FeatureId": "LUUID(\"e936d1e8-43da-a9f7-00c5-a221c1a81ebc\")"
150 | },
151 | "geometry": {
152 | "type": "Point",
153 | "coordinates": [
154 | 11.7612,
155 | 11.0213
156 | ]
157 | }
158 | },
159 | {
160 | "type": "Feature",
161 | "properties": {
162 | "_id": "LUUID(\"1d8eee62-6d37-2943-af64-0ba45cdda16b\")",
163 | "FeatureId": "LUUID(\"4ed889aa-6b9e-7f5e-3b86-6cbd936720b1\")"
164 | },
165 | "geometry": {
166 | "type": "Point",
167 | "coordinates": [
168 | 11.7612,
169 | 10.3677
170 | ]
171 | }
172 | },
173 | {
174 | "type": "Feature",
175 | "properties": {
176 | "_id": "LUUID(\"0f458140-020c-a144-a8da-a39467586ce6\")",
177 | "FeatureId": "LUUID(\"2b34cb22-c7c2-abf2-84b2-ee2fa62ca790\")"
178 | },
179 | "geometry": {
180 | "type": "Point",
181 | "coordinates": [
182 | 12.2337,
183 | 15.7094
184 | ]
185 | }
186 | },
187 | {
188 | "type": "Feature",
189 | "properties": {
190 | "_id": "LUUID(\"b5ebce8e-81bb-b84e-b066-addc3776e7c9\")",
191 | "FeatureId": "LUUID(\"f6dc093d-24a7-2ac2-8791-6821e4143803\")"
192 | },
193 | "geometry": {
194 | "type": "Point",
195 | "coordinates": [
196 | 12.2337,
197 | 15.056
198 | ]
199 | }
200 | },
201 | {
202 | "type": "Feature",
203 | "properties": {
204 | "_id": "LUUID(\"c3cc2e79-e0be-ec48-b053-0b538dd01edd\")",
205 | "FeatureId": "LUUID(\"b53821a6-23e4-fce3-db2c-d6748f324c15\")"
206 | },
207 | "geometry": {
208 | "type": "Point",
209 | "coordinates": [
210 | 12.2337,
211 | 12.911
212 | ]
213 | }
214 | },
215 | {
216 | "type": "Feature",
217 | "properties": {
218 | "_id": "LUUID(\"2aa69130-5c3f-5d4d-a094-59c25d0f1071\")",
219 | "FeatureId": "LUUID(\"9bb54400-42ce-478d-4f61-c5a2a749360a\")"
220 | },
221 | "geometry": {
222 | "type": "Point",
223 | "coordinates": [
224 | 12.2337,
225 | 12.2575
226 | ]
227 | }
228 | },
229 | {
230 | "type": "Feature",
231 | "properties": {
232 | "_id": "LUUID(\"81c9b85d-eea6-d24f-920b-5cb0d913b71c\")",
233 | "FeatureId": "LUUID(\"cef3b84b-9854-193b-b57c-63dbf4c4a9dc\")"
234 | },
235 | "geometry": {
236 | "type": "Point",
237 | "coordinates": [
238 | 12.2337,
239 | 11.0213
240 | ]
241 | }
242 | },
243 | {
244 | "type": "Feature",
245 | "properties": {
246 | "_id": "LUUID(\"6050272c-c085-fe47-8518-fb1303e3432e\")",
247 | "FeatureId": "LUUID(\"a0012879-9860-a676-858a-044fce228246\")"
248 | },
249 | "geometry": {
250 | "type": "Point",
251 | "coordinates": [
252 | 13.39995,
253 | 18.3654
254 | ]
255 | }
256 | },
257 | {
258 | "type": "Feature",
259 | "properties": {
260 | "_id": "LUUID(\"a9712fe7-aae4-c343-96a1-1f4f0122b358\")",
261 | "FeatureId": "LUUID(\"eca25869-e0f1-d702-2261-13dfe73b57f4\")"
262 | },
263 | "geometry": {
264 | "type": "Point",
265 | "coordinates": [
266 | 13.39995,
267 | 17.7354
268 | ]
269 | }
270 | },
271 | {
272 | "type": "Feature",
273 | "properties": {
274 | "_id": "LUUID(\"1e327b17-dee2-dc46-87a7-687e226307d5\")",
275 | "FeatureId": "LUUID(\"44037d4b-e9a8-7b2a-1b62-21b164a40aaf\")"
276 | },
277 | "geometry": {
278 | "type": "Point",
279 | "coordinates": [
280 | 15.87045,
281 | 18.3654
282 | ]
283 | }
284 | },
285 | {
286 | "type": "Feature",
287 | "properties": {
288 | "_id": "LUUID(\"084a28b1-1337-9348-97bf-d8955779148a\")",
289 | "FeatureId": "LUUID(\"14b0ab06-0875-27a1-e6fd-2eb30fa6068a\")"
290 | },
291 | "geometry": {
292 | "type": "Point",
293 | "coordinates": [
294 | 15.87045,
295 | 17.7354
296 | ]
297 | }
298 | },
299 | {
300 | "type": "Feature",
301 | "properties": {
302 | "_id": "LUUID(\"d7be478a-3bef-914f-8c5d-f690d2e01ab1\")",
303 | "FeatureId": "LUUID(\"b2d4f955-a472-1e8e-b0fe-aa8d01251f85\")"
304 | },
305 | "geometry": {
306 | "type": "Point",
307 | "coordinates": [
308 | 14.70925,
309 | 16.429
310 | ]
311 | }
312 | },
313 | {
314 | "type": "Feature",
315 | "properties": {
316 | "_id": "LUUID(\"d18a7922-24c2-f140-8e40-986b546045d3\")",
317 | "FeatureId": "LUUID(\"5a41656e-d428-685b-8168-c16738209e31\")"
318 | },
319 | "geometry": {
320 | "type": "Point",
321 | "coordinates": [
322 | 14.70515,
323 | 15.9567
324 | ]
325 | }
326 | },
327 | {
328 | "type": "Feature",
329 | "properties": {
330 | "_id": "LUUID(\"d73ebc93-e548-f44c-8f10-80db9bd9f40f\")",
331 | "FeatureId": "LUUID(\"6b600d53-4f5a-7ed2-662d-0fa5d2be3c0e\")"
332 | },
333 | "geometry": {
334 | "type": "Point",
335 | "coordinates": [
336 | 15.36285,
337 | 16.429
338 | ]
339 | }
340 | },
341 | {
342 | "type": "Feature",
343 | "properties": {
344 | "_id": "LUUID(\"1cc0517a-0d36-824d-83ff-0b5dddccf9ba\")",
345 | "FeatureId": "LUUID(\"ff9ecc0b-5571-abad-5319-69debdad163c\")"
346 | },
347 | "geometry": {
348 | "type": "Point",
349 | "coordinates": [
350 | 15.36675,
351 | 15.9567
352 | ]
353 | }
354 | },
355 | {
356 | "type": "Feature",
357 | "properties": {
358 | "_id": "LUUID(\"0f062f65-8a3d-7a4b-8726-077105dcb11e\")",
359 | "FeatureId": "LUUID(\"0e7ee077-8c51-8431-26f5-db87bd094a5b\")"
360 | },
361 | "geometry": {
362 | "type": "Point",
363 | "coordinates": [
364 | 14.70535,
365 | 15.0044
366 | ]
367 | }
368 | },
369 | {
370 | "type": "Feature",
371 | "properties": {
372 | "_id": "LUUID(\"2547c55d-caf1-9e48-a2e4-57d2ce000017\")",
373 | "FeatureId": "LUUID(\"8b7b01da-cc1e-2b8a-bdac-8c8313b13979\")"
374 | },
375 | "geometry": {
376 | "type": "Point",
377 | "coordinates": [
378 | 14.70925,
379 | 14.5319
380 | ]
381 | }
382 | },
383 | {
384 | "type": "Feature",
385 | "properties": {
386 | "_id": "LUUID(\"274d298c-d5ef-9145-8e15-55eafd318512\")",
387 | "FeatureId": "LUUID(\"d4897836-ec58-0407-acc6-0d963ad2a78a\")"
388 | },
389 | "geometry": {
390 | "type": "Point",
391 | "coordinates": [
392 | 15.36285,
393 | 15.0044
394 | ]
395 | }
396 | },
397 | {
398 | "type": "Feature",
399 | "properties": {
400 | "_id": "LUUID(\"5106da4c-a5ae-4b44-8f08-5cb8838cc40c\")",
401 | "FeatureId": "LUUID(\"5668e21f-4e50-2275-73f7-91bb8417792a\")"
402 | },
403 | "geometry": {
404 | "type": "Point",
405 | "coordinates": [
406 | 15.36285,
407 | 14.5319
408 | ]
409 | }
410 | },
411 | {
412 | "type": "Feature",
413 | "properties": {
414 | "_id": "LUUID(\"bf519e12-8bdb-0f46-b97f-632a20c2d653\")",
415 | "FeatureId": "LUUID(\"93897a49-6fee-2a20-413a-809c687b0853\")"
416 | },
417 | "geometry": {
418 | "type": "Point",
419 | "coordinates": [
420 | 12.2337,
421 | 10.3677
422 | ]
423 | }
424 | }
425 | ]
426 | }
--------------------------------------------------------------------------------
/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/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.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/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/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/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/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart' show rootBundle;
3 | import 'package:vector_map/vector_map.dart';
4 |
5 | void main() {
6 | runApp(ExampleWidget());
7 | }
8 |
9 | class ExampleWidget extends StatefulWidget {
10 | @override
11 | State createState() => ExampleState();
12 | }
13 |
14 | class ExampleState extends State {
15 | VectorMapController? _controller;
16 | MapDebugger debugger = MapDebugger();
17 |
18 | @override
19 | void initState() {
20 | super.initState();
21 | //String asset = 'assets/south_america.json';
22 | //String asset = 'assets/rooms.geojson';
23 | //String asset = 'assets/brazil_counties.json';
24 | //String asset = 'assets/polygons.json';
25 | //rootBundle.loadString(asset).then((geoJson) {
26 | _loadDataSources();
27 | }
28 |
29 | void _loadDataSources() async {
30 | /*
31 | String roomsGeoJson = await rootBundle.loadString('assets/rooms.geojson');
32 | MapDataSource rooms = await MapDataSource.geoJson(geoJson: roomsGeoJson);
33 | MapLayer roomsLayer = MapLayer(dataSource: rooms, theme: MapTheme(color: Colors.blue));
34 |
35 | String levelGeoJson = await rootBundle.loadString('assets/level.geojson');
36 | MapDataSource level = await MapDataSource.geoJson(geoJson: levelGeoJson);
37 |
38 | MapLayer levelLayer = MapLayer(
39 | dataSource: level,
40 | theme: MapTheme(color: Colors.black, contourColor: Colors.white));
41 |
42 | String workplacesGeoJson =
43 | await rootBundle.loadString('assets/workplaces.geojson');
44 | MapDataSource workplaces =
45 | await MapDataSource.geoJson(geoJson: workplacesGeoJson);
46 | MapLayer workplacesLayer = MapLayer(
47 | dataSource: workplaces,
48 | theme: MapTheme(color: Colors.white, contourColor: Colors.white));
49 | */
50 | String geoJson = await rootBundle.loadString('assets/polygons.json');
51 | MapDataSource ds = await MapDataSource.geoJson(geoJson: geoJson);
52 | MapLayer layer = MapLayer(dataSource: ds);
53 |
54 | setState(() {
55 | _controller =
56 | VectorMapController(layers: [layer], delayToRefreshResolution: 0);
57 | //_controller= VectorMapController(layers: [roomsLayer, levelLayer, workplacesLayer]);
58 | });
59 | }
60 |
61 | @override
62 | Widget build(BuildContext context) {
63 | Widget? content;
64 | if (_controller != null) {
65 | VectorMap map = VectorMap(
66 | controller: _controller,
67 | clickListener: (feature) => print(feature.id),
68 | );
69 | Widget buttons = SingleChildScrollView(
70 | child: Row(children: [
71 | _buildFitButton(),
72 | SizedBox(width: 8),
73 | _buildModeButton(),
74 | SizedBox(width: 8),
75 | _buildZoomInButton(),
76 | SizedBox(width: 8),
77 | _buildZoomOutButton()
78 | ]));
79 |
80 | Widget buttonsAndMap = Column(children: [
81 | Padding(child: buttons, padding: EdgeInsets.only(bottom: 8)),
82 | Expanded(child: map)
83 | ]);
84 |
85 | content = buttonsAndMap;
86 | /*
87 | content = Row(children: [
88 | Expanded(child: buttonsAndMap),
89 | SizedBox(
90 | child: Padding(
91 | child: MapDebuggerWidget(debugger),
92 | padding: EdgeInsets.all(16)),
93 | width: 200)
94 | ]);
95 |
96 | */
97 | } else {
98 | content = Center(child: Text('Loading...'));
99 | }
100 |
101 | return MaterialApp(
102 | debugShowCheckedModeBanner: false,
103 | theme: ThemeData(scaffoldBackgroundColor: Colors.blue[800]!),
104 | home: Scaffold(
105 | body: SafeArea(
106 | child: Padding(child: content, padding: EdgeInsets.all(8)))));
107 | }
108 |
109 | Widget _buildFitButton() {
110 | return ElevatedButton(child: Text('Fit'), onPressed: _onFit);
111 | }
112 |
113 | void _onFit() {
114 | _controller?.fit();
115 | }
116 |
117 | Widget _buildModeButton() {
118 | return ElevatedButton(child: Text('Change mode'), onPressed: _onMode);
119 | }
120 |
121 | void _onMode() {
122 | VectorMapMode mode = _controller!.mode == VectorMapMode.autoFit
123 | ? VectorMapMode.panAndZoom
124 | : VectorMapMode.autoFit;
125 | _controller!.mode = mode;
126 | }
127 |
128 | Widget _buildZoomInButton() {
129 | return ElevatedButton(child: Text('Zoom in'), onPressed: _onZoomIn);
130 | }
131 |
132 | void _onZoomIn() {
133 | _controller!.zoomOnCenter(true);
134 | }
135 |
136 | Widget _buildZoomOutButton() {
137 | return ElevatedButton(child: Text('Zoom out'), onPressed: _onZoomOut);
138 | }
139 |
140 | void _onZoomOut() {
141 | _controller!.zoomOnCenter(false);
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/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.8.2"
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.0"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.3.1"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.15.0"
46 | fake_async:
47 | dependency: transitive
48 | description:
49 | name: fake_async
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.2.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.3"
77 | meta:
78 | dependency: transitive
79 | description:
80 | name: meta
81 | url: "https://pub.dartlang.org"
82 | source: hosted
83 | version: "1.7.0"
84 | path:
85 | dependency: transitive
86 | description:
87 | name: path
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "1.8.0"
91 | sky_engine:
92 | dependency: transitive
93 | description: flutter
94 | source: sdk
95 | version: "0.0.99"
96 | source_span:
97 | dependency: transitive
98 | description:
99 | name: source_span
100 | url: "https://pub.dartlang.org"
101 | source: hosted
102 | version: "1.8.1"
103 | stack_trace:
104 | dependency: transitive
105 | description:
106 | name: stack_trace
107 | url: "https://pub.dartlang.org"
108 | source: hosted
109 | version: "1.10.0"
110 | stream_channel:
111 | dependency: transitive
112 | description:
113 | name: stream_channel
114 | url: "https://pub.dartlang.org"
115 | source: hosted
116 | version: "2.1.0"
117 | string_scanner:
118 | dependency: transitive
119 | description:
120 | name: string_scanner
121 | url: "https://pub.dartlang.org"
122 | source: hosted
123 | version: "1.1.0"
124 | term_glyph:
125 | dependency: transitive
126 | description:
127 | name: term_glyph
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "1.2.0"
131 | test_api:
132 | dependency: transitive
133 | description:
134 | name: test_api
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "0.4.8"
138 | typed_data:
139 | dependency: transitive
140 | description:
141 | name: typed_data
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "1.3.0"
145 | vector_map:
146 | dependency: "direct main"
147 | description:
148 | path: ".."
149 | relative: true
150 | source: path
151 | version: "0.6.1+2"
152 | vector_math:
153 | dependency: transitive
154 | description:
155 | name: vector_math
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "2.1.1"
159 | sdks:
160 | dart: ">=2.14.0 <3.0.0"
161 | flutter: ">=1.17.0"
162 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: '>=2.12.0 <3.0.0'
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 | vector_map:
27 | path: ../
28 |
29 | dev_dependencies:
30 | flutter_test:
31 | sdk: flutter
32 |
33 | # For information on the generic Dart part of this file, see the
34 | # following page: https://dart.dev/tools/pub/pubspec
35 |
36 | # The following section is specific to Flutter.
37 | flutter:
38 |
39 | # The following line ensures that the Material Icons font is
40 | # included with your application, so that you can use the icons in
41 | # the material Icons class.
42 | uses-material-design: true
43 |
44 | # To add assets to your application, add an assets section, like this:
45 | assets:
46 | - assets/south_america.json
47 | - assets/brazil_counties.json
48 | - assets/polygons.json
49 | - assets/workplaces.geojson
50 | - assets/rooms.geojson
51 | - assets/level.geojson
52 |
53 | # An image asset can refer to one or more resolution-specific "variants", see
54 | # https://flutter.dev/assets-and-images/#resolution-aware.
55 |
56 | # For details regarding adding assets from package dependencies, see
57 | # https://flutter.dev/assets-and-images/#from-packages
58 |
59 | # To add custom fonts to your application, add a fonts section here,
60 | # in this "flutter" section. Each entry in this list should have a
61 | # "family" key with the font family name, and a "fonts" key with a
62 | # list giving the asset and other descriptors for the font. For
63 | # example:
64 | # fonts:
65 | # - family: Schyler
66 | # fonts:
67 | # - asset: fonts/Schyler-Regular.ttf
68 | # - asset: fonts/Schyler-Italic.ttf
69 | # style: italic
70 | # - family: Trajan Pro
71 | # fonts:
72 | # - asset: fonts/TrajanPro.ttf
73 | # - asset: fonts/TrajanPro_Bold.ttf
74 | # weight: 700
75 | #
76 | # For details regarding fonts from package dependencies,
77 | # see https://flutter.dev/custom-fonts/#from-packages
78 |
--------------------------------------------------------------------------------
/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/web/favicon.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caduandrade/vector_map_flutter/34c10c2835b111d23a85d930ae50769c98d117ff/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | example
30 |
31 |
32 |
33 |
36 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "short_name": "example",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/lib/src/addon/legend/legend.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 | import 'package:vector_map/src/addon/map_addon.dart';
3 | import 'package:vector_map/src/data/map_layer.dart';
4 |
5 | /// Abstract legend
6 | ///
7 | /// Allows customize [padding], [margin] and [decoration]
8 | abstract class Legend extends MapAddon {
9 | /// Builds a legend
10 | Legend(
11 | {required this.layer,
12 | EdgeInsetsGeometry? padding,
13 | EdgeInsetsGeometry? margin,
14 | Decoration? decoration})
15 | : super(padding: padding, decoration: decoration, margin: margin);
16 | final MapLayer layer;
17 | }
18 |
--------------------------------------------------------------------------------
/lib/src/addon/map_addon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 | import 'package:vector_map/src/data/map_feature.dart';
3 | import 'package:vector_map/src/vector_map_api.dart';
4 |
5 | /// Allows to add components on the [VectorMap]
6 | abstract class MapAddon {
7 | MapAddon({this.padding, this.decoration, this.margin});
8 |
9 | /// Empty space to inscribe inside the [decoration]. The [MapAddon] widget, if any, is
10 | /// placed inside this padding.
11 | ///
12 | /// This padding is in addition to any padding inherent in the [decoration];
13 | /// see [Decoration.padding].
14 | final EdgeInsetsGeometry? padding;
15 |
16 | /// The decoration to paint behind the [MapAddon] widget.
17 | final Decoration? decoration;
18 |
19 | /// Empty space to surround the [decoration] and [MapAddon] widget.
20 | final EdgeInsetsGeometry? margin;
21 |
22 | /// Builds the [Widget] for this addon
23 | Widget buildWidget(
24 | {required BuildContext context,
25 | required VectorMapApi mapApi,
26 | MapFeature? hover});
27 | }
28 |
--------------------------------------------------------------------------------
/lib/src/data/geometries.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 | import 'dart:math' as math;
3 |
4 | import 'package:flutter/rendering.dart';
5 | import 'package:vector_map/src/data/simplified_path.dart';
6 | import 'package:vector_map/src/simplifier.dart';
7 |
8 | /// Abstract map geometry.
9 | mixin MapGeometry {
10 | Rect get bounds;
11 |
12 | int get pointsCount;
13 | }
14 |
15 | /// Point geometry.
16 | class MapPoint extends Offset with MapGeometry {
17 | MapPoint(double x, double y) : super(x, y);
18 |
19 | double get x => dx;
20 |
21 | double get y => dy;
22 |
23 | @override
24 | String toString() {
25 | return 'MapPoint{x: $x, y: $y}';
26 | }
27 |
28 | @override
29 | Rect get bounds => Rect.fromLTWH(x, y, 0, 0);
30 |
31 | @override
32 | int get pointsCount => 1;
33 | }
34 |
35 | /// Line string geometry.
36 | class MapLineString with MapGeometry {
37 | final UnmodifiableListView points;
38 | final Rect bounds;
39 |
40 | MapLineString._(this.points, this.bounds);
41 |
42 | factory MapLineString.coordinates(List coordinates) {
43 | List points = [];
44 | for (int i = 0; i < coordinates.length; i = i + 2) {
45 | if (i < coordinates.length - 1) {
46 | double x = coordinates[i];
47 | double y = coordinates[i + 1];
48 | points.add(MapPoint(x, y));
49 | }
50 | }
51 | return MapLineString(points);
52 | }
53 |
54 | factory MapLineString(List points) {
55 | //TODO exception for insufficient number of points?
56 | MapPoint first = points.first;
57 | double left = first.dx;
58 | double right = first.dx;
59 | double top = first.dy;
60 | double bottom = first.dy;
61 |
62 | for (int i = 1; i < points.length; i++) {
63 | MapPoint point = points[i];
64 | left = math.min(point.dx, left);
65 | right = math.max(point.dx, right);
66 | bottom = math.max(point.dy, bottom);
67 | top = math.min(point.dy, top);
68 | }
69 | Rect bounds = Rect.fromLTRB(left, top, right, bottom);
70 | return MapLineString._(UnmodifiableListView(points), bounds);
71 | }
72 |
73 | @override
74 | int get pointsCount => points.length;
75 |
76 | SimplifiedPath toSimplifiedPath(
77 | Matrix4 worldToCanvas, GeometrySimplifier simplifier) {
78 | Path path = Path();
79 | List simplifiedPoints =
80 | simplifier.simplify(worldToCanvas, points);
81 | for (int i = 0; i < simplifiedPoints.length; i++) {
82 | MapPoint point = simplifiedPoints[i];
83 | if (i == 0) {
84 | path.moveTo(point.dx, point.dy);
85 | } else {
86 | path.lineTo(point.dx, point.dy);
87 | }
88 | }
89 | return SimplifiedPath(path, simplifiedPoints.length);
90 | }
91 | }
92 |
93 | /// Multi line string geometry.
94 | class MapMultiLineString with MapGeometry {
95 | final UnmodifiableListView linesString;
96 | final Rect bounds;
97 |
98 | MapMultiLineString._(this.linesString, this.bounds);
99 |
100 | factory MapMultiLineString(List linesString) {
101 | Rect bounds = linesString.first.bounds;
102 | for (int i = 1; i < linesString.length; i++) {
103 | bounds = bounds.expandToInclude(linesString[i].bounds);
104 | }
105 | return MapMultiLineString._(
106 | UnmodifiableListView(linesString), bounds);
107 | }
108 |
109 | @override
110 | int get pointsCount => _getPointsCount();
111 |
112 | /// Gets the count of points.
113 | int _getPointsCount() {
114 | int count = 0;
115 | for (MapLineString line in linesString) {
116 | count += line.pointsCount;
117 | }
118 | return count;
119 | }
120 | }
121 |
122 | /// Line ring geometry.
123 | class MapLinearRing with MapGeometry {
124 | final UnmodifiableListView points;
125 | final Rect bounds;
126 |
127 | MapLinearRing._(this.points, this.bounds);
128 |
129 | factory MapLinearRing.coordinates(List coordinates) {
130 | List points = [];
131 | for (int i = 0; i < coordinates.length; i = i + 2) {
132 | if (i < coordinates.length - 1) {
133 | double x = coordinates[i];
134 | double y = coordinates[i + 1];
135 | points.add(MapPoint(x, y));
136 | }
137 | }
138 | return MapLinearRing(points);
139 | }
140 |
141 | factory MapLinearRing(List points) {
142 | //TODO exception for insufficient number of points?
143 | MapPoint first = points.first;
144 | double left = first.dx;
145 | double right = first.dx;
146 | double top = first.dy;
147 | double bottom = first.dy;
148 |
149 | for (int i = 1; i < points.length; i++) {
150 | MapPoint point = points[i];
151 | left = math.min(point.dx, left);
152 | right = math.max(point.dx, right);
153 | bottom = math.max(point.dy, bottom);
154 | top = math.min(point.dy, top);
155 | }
156 | Rect bounds = Rect.fromLTRB(left, top, right, bottom);
157 | return MapLinearRing._(UnmodifiableListView(points), bounds);
158 | }
159 |
160 | @override
161 | int get pointsCount => points.length;
162 |
163 | SimplifiedPath toSimplifiedPath(
164 | Matrix4 worldToCanvas, GeometrySimplifier simplifier) {
165 | Path path = Path();
166 | List simplifiedPoints =
167 | simplifier.simplify(worldToCanvas, points);
168 | for (int i = 0; i < simplifiedPoints.length; i++) {
169 | MapPoint point = simplifiedPoints[i];
170 | if (i == 0) {
171 | path.moveTo(point.dx, point.dy);
172 | } else {
173 | path.lineTo(point.dx, point.dy);
174 | }
175 | }
176 | path.close();
177 | return SimplifiedPath(path, simplifiedPoints.length);
178 | }
179 | }
180 |
181 | /// Polygon geometry.
182 | class MapPolygon with MapGeometry {
183 | final MapLinearRing externalRing;
184 | final UnmodifiableListView internalRings;
185 | final Rect bounds;
186 |
187 | MapPolygon._(this.externalRing, this.internalRings, this.bounds);
188 |
189 | factory MapPolygon.coordinates(List coordinates) {
190 | List externalPoints = [];
191 | List internalRings = [];
192 | List points = [];
193 | for (int i = 0; i < coordinates.length; i = i + 2) {
194 | if (i < coordinates.length - 1) {
195 | double x = coordinates[i];
196 | double y = coordinates[i + 1];
197 | points.add(MapPoint(x, y));
198 | if (points.length >= 3) {
199 | if (points.first.x == x && points.first.y == y) {
200 | // closing ring
201 | if (externalPoints.length == 0) {
202 | externalPoints = points;
203 | } else {
204 | internalRings.add(MapLinearRing(points));
205 | }
206 | points = [];
207 | }
208 | }
209 | }
210 | }
211 | return MapPolygon(MapLinearRing(externalPoints), internalRings);
212 | }
213 |
214 | factory MapPolygon(
215 | MapLinearRing externalRing, List? internalRings) {
216 | Rect bounds = externalRing.bounds;
217 |
218 | List internal = internalRings != null ? internalRings : [];
219 | for (MapLinearRing linearRing in internal) {
220 | bounds = bounds.expandToInclude(linearRing.bounds);
221 | }
222 | return MapPolygon._(
223 | externalRing, UnmodifiableListView(internal), bounds);
224 | }
225 |
226 | @override
227 | int get pointsCount => _getPointsCount();
228 |
229 | int _getPointsCount() {
230 | int count = externalRing.pointsCount;
231 | for (MapLinearRing ring in internalRings) {
232 | count += ring.pointsCount;
233 | }
234 | return count;
235 | }
236 |
237 | SimplifiedPath toSimplifiedPath(
238 | Matrix4 worldToCanvas, GeometrySimplifier simplifier) {
239 | Path path = Path()..fillType = PathFillType.evenOdd;
240 |
241 | SimplifiedPath simplifiedPath =
242 | externalRing.toSimplifiedPath(worldToCanvas, simplifier);
243 | int pointsCount = simplifiedPath.pointsCount;
244 | path.addPath(simplifiedPath.path, Offset.zero);
245 | for (MapLinearRing ring in internalRings) {
246 | simplifiedPath = ring.toSimplifiedPath(worldToCanvas, simplifier);
247 | pointsCount += simplifiedPath.pointsCount;
248 | path.addPath(simplifiedPath.path, Offset.zero);
249 | }
250 | return SimplifiedPath(path, pointsCount);
251 | }
252 | }
253 |
254 | /// Multi polygon geometry.
255 | class MapMultiPolygon with MapGeometry {
256 | final UnmodifiableListView polygons;
257 | final Rect bounds;
258 |
259 | MapMultiPolygon._(this.polygons, this.bounds);
260 |
261 | factory MapMultiPolygon(List polygons) {
262 | Rect bounds = polygons.first.bounds;
263 | for (int i = 1; i < polygons.length; i++) {
264 | bounds = bounds.expandToInclude(polygons[i].bounds);
265 | }
266 | return MapMultiPolygon._(
267 | UnmodifiableListView(polygons), bounds);
268 | }
269 |
270 | @override
271 | int get pointsCount => _getPointsCount();
272 |
273 | /// Gets the count of points.
274 | int _getPointsCount() {
275 | int count = 0;
276 | for (MapPolygon polygon in polygons) {
277 | count += polygon.pointsCount;
278 | }
279 | return count;
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/lib/src/data/map_data_source.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 | import 'dart:ui';
3 |
4 | import 'package:vector_map/src/data/geometries.dart';
5 | import 'package:vector_map/src/data/map_feature.dart';
6 | import 'package:vector_map/src/data/property_limits.dart';
7 | import 'package:vector_map/src/data_reader.dart';
8 |
9 | /// [VectorMap] data source.
10 | class MapDataSource {
11 | MapDataSource._(
12 | {required this.features,
13 | required this.bounds,
14 | required this.pointsCount,
15 | Map? limits})
16 | : this._limits = limits;
17 |
18 | final UnmodifiableMapView features;
19 | final Rect? bounds;
20 | final int pointsCount;
21 | final Map? _limits;
22 |
23 | /// Create a [MapDataSource] from a list of [MapFeature].
24 | static MapDataSource fromFeatures(List features) {
25 | Rect? boundsFromGeometry;
26 | int pointsCount = 0;
27 | if (features.isNotEmpty) {
28 | boundsFromGeometry = features.first.geometry.bounds;
29 | }
30 | Map limits = Map();
31 | Map featuresMap = Map();
32 | for (MapFeature feature in features) {
33 | featuresMap[feature.id] = feature;
34 | pointsCount += feature.geometry.pointsCount;
35 | if (boundsFromGeometry == null) {
36 | boundsFromGeometry = feature.geometry.bounds;
37 | } else {
38 | boundsFromGeometry =
39 | boundsFromGeometry.expandToInclude(feature.geometry.bounds);
40 | }
41 | if (feature.properties != null) {
42 | feature.properties!.entries.forEach((entry) {
43 | dynamic value = entry.value;
44 | double? doubleValue;
45 | if (value is int) {
46 | doubleValue = value.toDouble();
47 | } else if (value is double) {
48 | doubleValue = value;
49 | }
50 | if (doubleValue != null) {
51 | String key = entry.key;
52 | if (limits.containsKey(key)) {
53 | PropertyLimits propertyLimits = limits[key]!;
54 | propertyLimits.expand(doubleValue);
55 | } else {
56 | limits[key] = PropertyLimits(doubleValue);
57 | }
58 | }
59 | });
60 | }
61 | }
62 |
63 | return MapDataSource._(
64 | features: UnmodifiableMapView(featuresMap),
65 | bounds: boundsFromGeometry,
66 | pointsCount: pointsCount,
67 | limits: limits.isNotEmpty ? limits : null);
68 | }
69 |
70 | /// Loads a [MapDataSource] from GeoJSON.
71 | ///
72 | /// Geometries are always loaded.
73 | /// The [keys] argument defines which properties must be loaded.
74 | /// The [parseToNumber] argument defines which properties will have
75 | /// numeric values in quotes parsed to numbers.
76 | static Future geoJson(
77 | {required String geoJson,
78 | String? labelKey,
79 | List? keys,
80 | List? parseToNumber,
81 | String? colorKey,
82 | ColorValueFormat colorValueFormat = ColorValueFormat.hex}) async {
83 | MapFeatureReader reader = MapFeatureReader(
84 | labelKey: labelKey,
85 | keys: keys != null ? keys.toSet() : null,
86 | parseToNumber: parseToNumber != null ? parseToNumber.toSet() : null,
87 | colorKey: colorKey,
88 | colorValueFormat: colorValueFormat);
89 |
90 | List features = await reader.read(geoJson);
91 | return fromFeatures(features);
92 | }
93 |
94 | /// Loads a [MapDataSource] from geometries.
95 | /// [MapDataSource] features will have no properties.
96 | factory MapDataSource.geometries(List geometries) {
97 | Rect? boundsFromGeometry;
98 | int pointsCount = 0;
99 | Map featuresMap = Map();
100 | int id = 1;
101 | for (MapGeometry geometry in geometries) {
102 | featuresMap[id] = MapFeature(id: id, geometry: geometry);
103 | pointsCount += geometry.pointsCount;
104 | if (boundsFromGeometry == null) {
105 | boundsFromGeometry = geometry.bounds;
106 | } else {
107 | boundsFromGeometry =
108 | boundsFromGeometry.expandToInclude(geometry.bounds);
109 | }
110 | id++;
111 | }
112 |
113 | return MapDataSource._(
114 | features: UnmodifiableMapView(featuresMap),
115 | bounds: boundsFromGeometry,
116 | pointsCount: pointsCount);
117 | }
118 |
119 | PropertyLimits? getPropertyLimits(String key) {
120 | if (_limits != null && _limits!.containsKey(key)) {
121 | return _limits![key]!;
122 | }
123 | return null;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/lib/src/data/map_feature.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 |
3 | import 'package:vector_map/src/data/geometries.dart';
4 |
5 | /// A representation of a real-world object on a map.
6 | class MapFeature {
7 | MapFeature(
8 | {required this.id,
9 | required this.geometry,
10 | Map? properties,
11 | this.label})
12 | : this.properties =
13 | properties != null ? UnmodifiableMapView(properties) : null;
14 |
15 | final int id;
16 | final String? label;
17 | final UnmodifiableMapView? properties;
18 | final MapGeometry geometry;
19 |
20 | dynamic getValue(String key) {
21 | if (properties != null && properties!.containsKey(key)) {
22 | return properties![key];
23 | }
24 | return null;
25 | }
26 |
27 | double? getDoubleValue(String key) {
28 | dynamic d = getValue(key);
29 | if (d != null) {
30 | if (d is double) {
31 | return d;
32 | } else if (d is int) {
33 | return d.toDouble();
34 | }
35 | }
36 | return null;
37 | }
38 |
39 | @override
40 | bool operator ==(Object other) =>
41 | identical(this, other) ||
42 | other is MapFeature && runtimeType == other.runtimeType && id == other.id;
43 |
44 | @override
45 | int get hashCode => id.hashCode;
46 | }
47 |
--------------------------------------------------------------------------------
/lib/src/data/map_layer.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:vector_map/src/data/map_data_source.dart';
4 | import 'package:vector_map/src/theme/map_highlight_theme.dart';
5 | import 'package:vector_map/src/theme/map_theme.dart';
6 |
7 | /// Layer for [VectorMap].
8 | class MapLayer {
9 | MapLayer(
10 | {int? id,
11 | required this.dataSource,
12 | MapTheme? theme,
13 | this.highlightTheme,
14 | this.name})
15 | : this.id = id != null ? id : _randomId(),
16 | this.theme = theme != null ? theme : MapTheme();
17 |
18 | final int id;
19 | final MapDataSource dataSource;
20 | final MapTheme theme;
21 | final MapHighlightTheme? highlightTheme;
22 | final String? name;
23 |
24 | /// Indicates if the hover is drawable, if there is any highlight theme and
25 | /// if it has a set value.
26 | bool get hoverDrawable {
27 | return highlightTheme != null && highlightTheme!.hasValue();
28 | }
29 |
30 | @override
31 | bool operator ==(Object other) =>
32 | identical(this, other) ||
33 | other is MapLayer && runtimeType == other.runtimeType && id == other.id;
34 |
35 | @override
36 | int get hashCode => id.hashCode;
37 |
38 | /// Gets a random layer id.
39 | static int _randomId() {
40 | Random random = Random();
41 | return random.nextInt(9999999);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/src/data/property_limits.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math' as math;
2 |
3 | /// Stores the number limits, max and min, for a given feature property.
4 | class PropertyLimits {
5 | double _max;
6 | double _min;
7 |
8 | PropertyLimits(double value)
9 | : this._max = value,
10 | this._min = value;
11 |
12 | double get max => _max;
13 |
14 | double get min => _min;
15 |
16 | expand(double value) {
17 | _max = math.max(_max, value);
18 | _min = math.min(_min, value);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/src/data/simplified_path.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | /// Stores a simplified path generated from the original [MapFeature] geometry.
4 | class SimplifiedPath {
5 | SimplifiedPath(this.path, this.pointsCount);
6 |
7 | final Path path;
8 | final int pointsCount;
9 | }
10 |
--------------------------------------------------------------------------------
/lib/src/data_reader.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:vector_map/src/data/geometries.dart';
4 | import 'package:vector_map/src/data/map_feature.dart';
5 | import 'package:vector_map/src/error.dart';
6 |
7 | /// Generic GeoJSON reader.
8 | class _GeoJsonReaderBase {
9 | void _checkKeyOn(Map map, String key) {
10 | if (map.containsKey(key) == false) {
11 | throw VectorMapError.keyNotFound(key);
12 | }
13 | }
14 |
15 | MapGeometry _readGeometry(bool hasParent, Map map) {
16 | _checkKeyOn(map, 'type');
17 | final type = map['type'];
18 | switch (type) {
19 | //TODO other geometries
20 | case 'Point':
21 | return _readPoint(map);
22 | case 'MultiPoint':
23 | throw UnimplementedError();
24 | case 'LineString':
25 | return _readLineString(map);
26 | case 'MultiLineString':
27 | return _readMultiLineString(map);
28 | case 'Polygon':
29 | return _readPolygon(map);
30 | case 'MultiPolygon':
31 | return _readMultiPolygon(map);
32 | default:
33 | if (hasParent) {
34 | throw VectorMapError.invalidGeometryType(type);
35 | } else {
36 | throw VectorMapError.invalidType(type);
37 | }
38 | }
39 | }
40 |
41 | MapGeometry _readPoint(Map map) {
42 | _checkKeyOn(map, 'coordinates');
43 | List coordinates = map['coordinates'];
44 | if (coordinates.length == 2) {
45 | double x = _toDouble(coordinates[0]);
46 | double y = _toDouble(coordinates[1]);
47 | return MapPoint(x, y);
48 | }
49 |
50 | throw VectorMapError(
51 | 'Expected 2 coordinates but received ' + coordinates.length.toString());
52 | }
53 |
54 | MapGeometry _readLineString(Map map) {
55 | _checkKeyOn(map, 'coordinates');
56 | List coordinates = map['coordinates'];
57 | List points = [];
58 | for (List xy in coordinates) {
59 | double x = _toDouble(xy[0]);
60 | double y = _toDouble(xy[1]);
61 | points.add(MapPoint(x, y));
62 | }
63 | return MapLineString(points);
64 | }
65 |
66 | MapGeometry _readMultiLineString(Map map) {
67 | _checkKeyOn(map, 'coordinates');
68 | List coordinates = map['coordinates'];
69 | List lineString = [];
70 | for (List coords in coordinates) {
71 | List points = [];
72 | for (List xy in coords) {
73 | double x = _toDouble(xy[0]);
74 | double y = _toDouble(xy[1]);
75 | points.add(MapPoint(x, y));
76 | }
77 | lineString.add(MapLineString(points));
78 | }
79 | return MapMultiLineString(lineString);
80 | }
81 |
82 | MapGeometry _readPolygon(Map map) {
83 | late MapLinearRing externalRing;
84 | List internalRings = [];
85 |
86 | _checkKeyOn(map, 'coordinates');
87 | List rings = map['coordinates'];
88 | for (int i = 0; i < rings.length; i++) {
89 | List points = [];
90 | List ring = rings[i];
91 | for (List xy in ring) {
92 | double x = _toDouble(xy[0]);
93 | double y = _toDouble(xy[1]);
94 | points.add(MapPoint(x, y));
95 | }
96 | if (i == 0) {
97 | externalRing = MapLinearRing(points);
98 | } else {
99 | internalRings.add(MapLinearRing(points));
100 | }
101 | }
102 |
103 | return MapPolygon(externalRing, internalRings);
104 | }
105 |
106 | MapGeometry _readMultiPolygon(Map map) {
107 | _checkKeyOn(map, 'coordinates');
108 | List polygons = map['coordinates'];
109 |
110 | List mapPolygons = [];
111 | for (List rings in polygons) {
112 | late MapLinearRing externalRing;
113 | List internalRings = [];
114 |
115 | for (int i = 0; i < rings.length; i++) {
116 | List points = [];
117 | List ring = rings[i];
118 | for (List xy in ring) {
119 | double x = _toDouble(xy[0]);
120 | double y = _toDouble(xy[1]);
121 | points.add(MapPoint(x, y));
122 | }
123 | if (i == 0) {
124 | externalRing = MapLinearRing(points);
125 | } else {
126 | internalRings.add(MapLinearRing(points));
127 | }
128 | }
129 | MapPolygon polygon = MapPolygon(externalRing, internalRings);
130 | mapPolygons.add(polygon);
131 | }
132 |
133 | return MapMultiPolygon(mapPolygons);
134 | }
135 |
136 | /// Parses a dynamic coordinate to [double].
137 | double _toDouble(dynamic coordinate) {
138 | if (coordinate is double) {
139 | return coordinate;
140 | } else if (coordinate is int) {
141 | return coordinate.toDouble();
142 | }
143 | // The coordinate shouldn't be a String but since it is, tries to parse.
144 | return double.parse(coordinate.toString());
145 | }
146 | }
147 |
148 | enum ColorValueFormat { hex }
149 |
150 | /// Properties read.
151 | class _Properties {
152 | _Properties({this.label, this.values});
153 |
154 | /// Label value extracted from [labelKey].
155 | final String? label;
156 | final Map? values;
157 | }
158 |
159 | /// [MapFeature] reader
160 | ///
161 | /// The [keys] argument defines which properties must be loaded.
162 | /// The [parseToNumber] argument defines which properties will have numeric
163 | /// values in quotes parsed to numbers.
164 | class MapFeatureReader extends _GeoJsonReaderBase {
165 | MapFeatureReader(
166 | {this.labelKey,
167 | this.keys,
168 | this.parseToNumber,
169 | this.colorKey,
170 | this.colorValueFormat = ColorValueFormat.hex});
171 |
172 | final List _list = [];
173 |
174 | final String? labelKey;
175 | final Set? keys;
176 | final Set? parseToNumber;
177 | final String? colorKey;
178 | final ColorValueFormat colorValueFormat;
179 |
180 | Future> read(String geoJson) async {
181 | Map map = json.decode(geoJson);
182 | await _readMap(map);
183 | return _list;
184 | }
185 |
186 | Future _readMap(Map map) async {
187 | _checkKeyOn(map, 'type');
188 |
189 | final type = map['type'];
190 |
191 | if (type == 'FeatureCollection') {
192 | _checkKeyOn(map, 'features');
193 | //TODO check if it is a Map?
194 | for (Map featureMap in map['features']) {
195 | _readFeature(featureMap);
196 | }
197 | } else if (type == 'GeometryCollection') {
198 | } else if (type == 'Feature') {
199 | _readFeature(map);
200 | } else {
201 | MapGeometry geometry = _readGeometry(false, map);
202 | _addFeature(geometry: geometry);
203 | }
204 | }
205 |
206 | void _readFeature(Map map) {
207 | _checkKeyOn(map, 'geometry');
208 | Map geometryMap = map['geometry'];
209 | MapGeometry geometry = _readGeometry(true, geometryMap);
210 | _Properties? properties;
211 | if ((labelKey != null || keys != null || colorKey != null) &&
212 | map.containsKey('properties')) {
213 | Map propertiesMap = map['properties'];
214 | properties = _readProperties(propertiesMap);
215 | }
216 | _addFeature(geometry: geometry, properties: properties);
217 | }
218 |
219 | _Properties _readProperties(Map map) {
220 | String? label;
221 | Map? values;
222 | if (labelKey != null && map.containsKey(labelKey)) {
223 | // converting dynamic to String
224 | label = map[labelKey].toString();
225 | }
226 | if (keys != null) {
227 | if (keys!.isNotEmpty) {
228 | Map valuesTmp = Map();
229 | for (String key in keys!) {
230 | if (map.containsKey(key)) {
231 | dynamic value = map[key];
232 | if (parseToNumber != null &&
233 | parseToNumber!.contains(key) &&
234 | value is String) {
235 | value = double.parse(value);
236 | }
237 | valuesTmp[key] = value;
238 | }
239 | }
240 | if (valuesTmp.isNotEmpty) {
241 | values = valuesTmp;
242 | }
243 | }
244 | }
245 | return _Properties(label: label, values: values);
246 | }
247 |
248 | void _addFeature({required MapGeometry geometry, _Properties? properties}) {
249 | _list.add(MapFeature(
250 | id: _list.length + 1,
251 | geometry: geometry,
252 | properties: properties?.values,
253 | label: properties?.label));
254 | }
255 | }
256 |
257 | /// GeoJSON geometry reader.
258 | class MapGeometryReader extends _GeoJsonReaderBase {
259 | final List _list = [];
260 |
261 | Future> geoJson(String geoJson) async {
262 | Map map = json.decode(geoJson);
263 | await _readMap(map);
264 | return _list;
265 | }
266 |
267 | Future _readMap(Map map) async {
268 | _checkKeyOn(map, 'type');
269 |
270 | final type = map['type'];
271 |
272 | if (type == 'FeatureCollection') {
273 | _checkKeyOn(map, 'features');
274 | //TODO check if it is a Map?
275 | for (Map featureMap in map['features']) {
276 | _readFeature(featureMap);
277 | }
278 | } else if (type == 'GeometryCollection') {
279 | } else if (type == 'Feature') {
280 | _readFeature(map);
281 | } else {
282 | MapGeometry geometry = _readGeometry(false, map);
283 | _list.add(geometry);
284 | }
285 | }
286 |
287 | void _readFeature(Map map) {
288 | _checkKeyOn(map, 'geometry');
289 | Map geometryMap = map['geometry'];
290 | MapGeometry geometry = _readGeometry(true, geometryMap);
291 | _list.add(geometry);
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/lib/src/debugger.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 | import 'package:vector_map/src/data/map_layer.dart';
3 | import 'package:vector_map/src/drawable/drawable_layer.dart';
4 | import 'package:vector_map/src/vector_map_mode.dart';
5 |
6 | class DurationDebugger extends ChangeNotifier {
7 | DurationDebugger(VoidCallback listener) {
8 | addListener(listener);
9 | }
10 |
11 | int _milliseconds = 0;
12 | int get milliseconds => _milliseconds;
13 |
14 | DateTime? _lastStartTime;
15 |
16 | void clear() {
17 | _milliseconds = 0;
18 | _lastStartTime = null;
19 | }
20 |
21 | void open() {
22 | _lastStartTime = DateTime.now();
23 | }
24 |
25 | closeAndInc() {
26 | if (_lastStartTime != null) {
27 | DateTime end = DateTime.now();
28 | Duration duration = end.difference(_lastStartTime!);
29 | _milliseconds += duration.inMilliseconds;
30 | _lastStartTime = null;
31 | notifyListeners();
32 | }
33 | }
34 | }
35 |
36 | class MapDebugger extends ChangeNotifier {
37 | MapDebugger() {
38 | drawableBuildDuration = DurationDebugger(notifyListeners);
39 | bufferBuildDuration = DurationDebugger(notifyListeners);
40 | }
41 |
42 | int _layersCount = 0;
43 | int _chunksCount = 0;
44 | int _featuresCount = 0;
45 | int _originalPointsCount = 0;
46 | int _simplifiedPointsCount = 0;
47 | Offset? _mouseHoverWorld;
48 | Offset? _mouseHoverCanvas;
49 |
50 | late DurationDebugger drawableBuildDuration;
51 | late DurationDebugger bufferBuildDuration;
52 |
53 | String? _mode;
54 |
55 | void updateMode(VectorMapMode mode) {
56 | if (mode == VectorMapMode.autoFit) {
57 | _mode = "auto fit";
58 | } else if (mode == VectorMapMode.panAndZoom) {
59 | _mode = "pan and zoom";
60 | } else {
61 | _mode = null;
62 | }
63 | }
64 |
65 | void updateLayers(List drawableLayers, int chunksCount) {
66 | _layersCount = drawableLayers.length;
67 | _chunksCount = chunksCount;
68 | for (DrawableLayer drawableLayer in drawableLayers) {
69 | MapLayer layer = drawableLayer.layer;
70 | _featuresCount += layer.dataSource.features.length;
71 | _originalPointsCount += layer.dataSource.pointsCount;
72 | }
73 | _simplifiedPointsCount = 0;
74 | notifyListeners();
75 | }
76 |
77 | void updateMouseHover({Offset? worldCoordinate, Offset? locationOnCanvas}) {
78 | this._mouseHoverWorld = worldCoordinate;
79 | this._mouseHoverCanvas = locationOnCanvas;
80 | notifyListeners();
81 | }
82 |
83 | void updateSimplifiedPointsCount(int simplifiedPointsCount) {
84 | _simplifiedPointsCount = simplifiedPointsCount;
85 | notifyListeners();
86 | }
87 | }
88 |
89 | class MapDebuggerWidget extends StatefulWidget {
90 | MapDebuggerWidget(this.debugger);
91 |
92 | final MapDebugger? debugger;
93 |
94 | @override
95 | State createState() {
96 | return MapDebuggerState();
97 | }
98 | }
99 |
100 | class MapDebuggerState extends State {
101 | ScrollController _controller = ScrollController();
102 |
103 | String formatInt(int value) {
104 | String str = value.toString();
105 | String fmt = '';
106 | int indexGroup = 3 - str.length % 3;
107 | if (indexGroup == 3) {
108 | indexGroup = 0;
109 | }
110 | for (int i = 0; i < str.length; i++) {
111 | fmt += str.substring(i, i + 1);
112 | indexGroup++;
113 | if (indexGroup == 3 && i < str.length - 1) {
114 | fmt += ',';
115 | indexGroup = 0;
116 | }
117 | }
118 | return fmt;
119 | }
120 |
121 | @override
122 | Widget build(BuildContext context) {
123 | if (widget.debugger == null) {
124 | return Container();
125 | }
126 | MapDebugger d = widget.debugger!;
127 |
128 | int drawableBuildDuration = d.drawableBuildDuration.milliseconds;
129 | int bufferBuildDuration = d.bufferBuildDuration.milliseconds;
130 | int multiResolutionDuration = drawableBuildDuration + bufferBuildDuration;
131 |
132 | return SingleChildScrollView(
133 | controller: _controller,
134 | child: Container(
135 | child: Column(children: [
136 | _title('Quantities'),
137 | _int('Layers: ', d._layersCount),
138 | _int(' • Chunks: ', d._chunksCount),
139 | _int('Features: ', d._featuresCount),
140 | _int('Original points: ', d._originalPointsCount),
141 | _int('Simplified points: ', d._simplifiedPointsCount),
142 | _title('Last durations'),
143 | _milliseconds('Drawables build: ', multiResolutionDuration),
144 | _milliseconds(
145 | ' • Simplified geometries: ', drawableBuildDuration),
146 | _milliseconds(' • Buffers: ', bufferBuildDuration),
147 | _title('Cursor location'),
148 | _offset('Canvas: ', d._mouseHoverCanvas),
149 | _offset('World: ', d._mouseHoverWorld),
150 | _title('Configurations'),
151 | _item('Mode: ', d._mode != null ? d._mode! : '')
152 | ], crossAxisAlignment: CrossAxisAlignment.start),
153 | width: 200,
154 | padding: EdgeInsets.all(8)));
155 | }
156 |
157 | Widget _title(String text) {
158 | return Padding(
159 | padding: EdgeInsets.fromLTRB(0, 12, 0, 12),
160 | child: Text(text,
161 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12)));
162 | }
163 |
164 | Widget _milliseconds(String label, int value) {
165 | return _item(label, formatInt(value) + ' ms');
166 | }
167 |
168 | Widget _int(String label, int value) {
169 | return _item(label, formatInt(value));
170 | }
171 |
172 | Widget _offset(String label, Offset? offset) {
173 | if (offset == null) {
174 | return _item(label, '');
175 | }
176 | return _item(label, offset.dx.toString() + ', ' + offset.dy.toString());
177 | }
178 |
179 | Widget _item(String label, String value) {
180 | return Padding(
181 | padding: EdgeInsets.fromLTRB(0, 4, 0, 0),
182 | child: RichText(
183 | text: new TextSpan(
184 | style: TextStyle(fontSize: 12),
185 | children: [
186 | new TextSpan(text: label),
187 | new TextSpan(
188 | text: value,
189 | style: new TextStyle(fontWeight: FontWeight.bold)),
190 | ],
191 | ),
192 | ));
193 | }
194 |
195 | @override
196 | void initState() {
197 | super.initState();
198 | widget.debugger?.addListener(_refresh);
199 | }
200 |
201 | @override
202 | void didUpdateWidget(MapDebuggerWidget oldWidget) {
203 | super.didUpdateWidget(oldWidget);
204 | oldWidget.debugger?.removeListener(_refresh);
205 | widget.debugger?.addListener(_refresh);
206 | }
207 |
208 | @override
209 | void dispose() {
210 | widget.debugger?.removeListener(_refresh);
211 | super.dispose();
212 | }
213 |
214 | void _refresh() {
215 | // avoid calling setState during build
216 | Future.delayed(Duration.zero, () {
217 | if (mounted) {
218 | setState(() {
219 | // rebuild
220 | });
221 | }
222 | });
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/lib/src/draw_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/rendering.dart';
2 | import 'package:vector_map/src/data/map_data_source.dart';
3 | import 'package:vector_map/src/data/map_feature.dart';
4 | import 'package:vector_map/src/data/map_layer.dart';
5 | import 'package:vector_map/src/drawable/drawable.dart';
6 | import 'package:vector_map/src/drawable/drawable_feature.dart';
7 | import 'package:vector_map/src/drawable/drawable_layer.dart';
8 | import 'package:vector_map/src/drawable/drawable_layer_chunk.dart';
9 | import 'package:vector_map/src/map_highlight.dart';
10 | import 'package:vector_map/src/theme/map_theme.dart';
11 |
12 | /// Draw utils for [VectorMap].
13 | class DrawUtils {
14 | /// Draws the features on a given canvas.
15 | ///
16 | /// Only features that match [highlightRule] will be drawn.
17 | static void draw(
18 | {required Canvas canvas,
19 | required DrawableLayerChunk chunk,
20 | required MapLayer layer,
21 | required double contourThickness,
22 | required double scale,
23 | required bool antiAlias,
24 | MapHighlight? highlightRule}) {
25 | MapDataSource dataSource = layer.dataSource;
26 | MapTheme theme = layer.theme;
27 | Color? highlightColor = layer.highlightTheme?.color;
28 |
29 | for (int index = 0; index < chunk.length; index++) {
30 | DrawableFeature drawableFeature = chunk.getDrawableFeature(index);
31 | MapFeature feature = drawableFeature.feature;
32 | Drawable? drawable = drawableFeature.drawable;
33 | if (drawable != null && drawable.visible && drawable.hasFill) {
34 | Color color;
35 | if (highlightColor != null &&
36 | highlightRule != null &&
37 | highlightRule.applies(feature)) {
38 | color = highlightColor;
39 | } else {
40 | color = MapTheme.getThemeOrDefaultColor(dataSource, feature, theme);
41 | }
42 | var paint = Paint()
43 | ..style = PaintingStyle.fill
44 | ..color = color
45 | ..isAntiAlias = antiAlias;
46 | drawable.drawOn(canvas, paint, scale);
47 | }
48 | }
49 |
50 | if (contourThickness > 0) {
51 | DrawUtils.drawContour(
52 | canvas: canvas,
53 | layer: layer,
54 | chunk: chunk,
55 | contourThickness: contourThickness,
56 | scale: scale,
57 | antiAlias: antiAlias,
58 | highlightRule: highlightRule);
59 | }
60 | }
61 |
62 | /// Draws the contour of the features on a given canvas.
63 | ///
64 | /// Only features that match [highlightRule] will be drawn.
65 | static void drawContour(
66 | {required Canvas canvas,
67 | required DrawableLayerChunk chunk,
68 | required MapLayer layer,
69 | required double contourThickness,
70 | required double scale,
71 | required bool antiAlias,
72 | MapHighlight? highlightRule}) {
73 | MapTheme theme = layer.theme;
74 |
75 | late Color contourColor;
76 | if (highlightRule != null && layer.highlightTheme?.contourColor != null) {
77 | contourColor = layer.highlightTheme!.contourColor!;
78 | } else {
79 | contourColor = theme.contourColor != null
80 | ? theme.contourColor!
81 | : MapTheme.defaultContourColor;
82 | }
83 |
84 | var paint = Paint()
85 | ..style = PaintingStyle.stroke
86 | ..color = contourColor
87 | ..strokeWidth = contourThickness / scale
88 | ..isAntiAlias = antiAlias;
89 |
90 | for (int index = 0; index < chunk.length; index++) {
91 | DrawableFeature drawableFeature = chunk.getDrawableFeature(index);
92 | Drawable? drawable = drawableFeature.drawable;
93 | if (drawable != null && drawable.visible) {
94 | if (highlightRule != null) {
95 | MapFeature feature = drawableFeature.feature;
96 | if (highlightRule.applies(feature) == false) {
97 | continue;
98 | }
99 | }
100 | drawable.drawOn(canvas, paint, scale);
101 | }
102 | }
103 | }
104 |
105 | /// Draws the features that match [MapMultiHighlight] on a given canvas.
106 | static void drawHighlight(
107 | {required Canvas canvas,
108 | required DrawableLayer drawableLayer,
109 | required Paint paint,
110 | required double scale,
111 | required bool fillOnly,
112 | required MapHighlight highlight}) {
113 | for (DrawableLayerChunk chunk in drawableLayer.chunks) {
114 | for (int index = 0; index < chunk.length; index++) {
115 | DrawableFeature drawableFeature = chunk.getDrawableFeature(index);
116 | MapFeature feature = drawableFeature.feature;
117 | Drawable? drawable = drawableFeature.drawable;
118 | if (drawable != null && drawable.visible) {
119 | if (fillOnly && drawable.hasFill == false) {
120 | continue;
121 | }
122 | if (highlight.applies(feature)) {
123 | drawable.drawOn(canvas, paint, scale);
124 | }
125 | }
126 | }
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/lib/src/drawable/circle_marker.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math' as math;
2 | import 'dart:ui';
3 |
4 | import 'package:vector_map/src/data/map_data_source.dart';
5 | import 'package:vector_map/src/data/map_feature.dart';
6 | import 'package:vector_map/src/data/property_limits.dart';
7 | import 'package:vector_map/src/drawable/marker.dart';
8 | import 'package:vector_map/src/error.dart';
9 |
10 | /// Defines a circle marker to be painted on the map.
11 | class CircleMaker extends Marker {
12 | CircleMaker(
13 | {required Offset offset,
14 | required double radius,
15 | required double scaledRadius})
16 | : this._bounds = Rect.fromLTWH(offset.dx - scaledRadius,
17 | offset.dy - scaledRadius, scaledRadius * 2, scaledRadius * 2),
18 | this._radius = radius,
19 | super(offset: offset);
20 |
21 | final Rect _bounds;
22 | final double _radius;
23 |
24 | @override
25 | bool contains(Offset offset) {
26 | return _bounds.contains(offset);
27 | }
28 |
29 | @override
30 | void drawMarkerOn(Canvas canvas, Paint paint, Offset offset, double scale) {
31 | canvas.drawCircle(offset, _radius / scale, paint);
32 | }
33 |
34 | @override
35 | Rect getBounds() {
36 | return _bounds;
37 | }
38 |
39 | @override
40 | bool get visible => _radius > 0 ? true : false;
41 |
42 | @override
43 | bool get hasFill => true;
44 | }
45 |
46 | /// A [CircleMaker] builder.
47 | class CircleMakerBuilder {
48 | /// Builds a fixed radius circle marker. The default [radius] value is [5].
49 | static MarkerBuilder fixed({double radius = 5}) {
50 | return _FixedRadius(radius: math.max(0, radius));
51 | }
52 |
53 | /// Builds a circle marker by mapping a property value to a radius.
54 | static MarkerBuilder map(
55 | {required String key, required Map radiuses}) {
56 | return _MappedValues(key: key, radiuses: radiuses);
57 | }
58 |
59 | /// Builds a circle marker using property values as radiuses.
60 | /// The type of the values must be numeric.
61 | static MarkerBuilder property({required String key}) {
62 | return _Property(key: key);
63 | }
64 |
65 | /// Builds a circle marker by proportionally mapping property
66 | /// values to defined minimum and maximum values.
67 | static MarkerBuilder proportion(
68 | {required String key,
69 | required double minRadius,
70 | required double maxRadius}) {
71 | if (maxRadius <= minRadius) {
72 | throw VectorMapError('maxRadius must be bigger than minRadius');
73 | }
74 | return _Proportion(key: key, minRadius: minRadius, maxRadius: maxRadius);
75 | }
76 | }
77 |
78 | /// Fixed radius [CircleMaker] builder.
79 | class _FixedRadius extends MarkerBuilder {
80 | _FixedRadius({required this.radius});
81 |
82 | final double radius;
83 |
84 | @override
85 | Marker build(
86 | {required MapDataSource dataSource,
87 | required MapFeature feature,
88 | required Offset offset,
89 | required double scale}) {
90 | return CircleMaker(
91 | offset: offset, radius: radius, scaledRadius: radius / scale);
92 | }
93 | }
94 |
95 | class _MappedValues extends MarkerBuilder {
96 | _MappedValues({required this.key, required this.radiuses});
97 |
98 | final String key;
99 | final Map radiuses;
100 |
101 | @override
102 | Marker build(
103 | {required MapDataSource dataSource,
104 | required MapFeature feature,
105 | required Offset offset,
106 | required double scale}) {
107 | double r = 0;
108 | dynamic value = feature.getValue(key);
109 | if (value != null && radiuses.containsKey(value)) {
110 | r = math.max(0, radiuses[value]!);
111 | }
112 | return CircleMaker(offset: offset, radius: r, scaledRadius: r / scale);
113 | }
114 | }
115 |
116 | class _Property extends MarkerBuilder {
117 | _Property({required this.key});
118 |
119 | final String key;
120 |
121 | @override
122 | Marker build(
123 | {required MapDataSource dataSource,
124 | required MapFeature feature,
125 | required Offset offset,
126 | required double scale}) {
127 | double r = 0;
128 | dynamic dynamicValue = feature.getValue(key);
129 | if (dynamicValue is int) {
130 | r = math.max(0, dynamicValue.toDouble());
131 | } else if (dynamicValue is double) {
132 | r = math.max(0, dynamicValue);
133 | }
134 |
135 | return CircleMaker(offset: offset, radius: r, scaledRadius: r / scale);
136 | }
137 | }
138 |
139 | class _Proportion extends MarkerBuilder {
140 | _Proportion(
141 | {required this.key, required this.minRadius, required this.maxRadius});
142 |
143 | final String key;
144 | final double minRadius;
145 | final double maxRadius;
146 |
147 | @override
148 | Marker build(
149 | {required MapDataSource dataSource,
150 | required MapFeature feature,
151 | required Offset offset,
152 | required double scale}) {
153 | double radius = 0;
154 |
155 | PropertyLimits? propertyLimits = dataSource.getPropertyLimits(key);
156 | if (propertyLimits != null) {
157 | dynamic dynamicValue = feature.getValue(key);
158 | if (dynamicValue is int) {
159 | radius = _radius(
160 | propertyLimits.min, propertyLimits.max, dynamicValue.toDouble());
161 | } else if (dynamicValue is double) {
162 | radius = _radius(propertyLimits.min, propertyLimits.max, dynamicValue);
163 | }
164 | }
165 |
166 | return CircleMaker(
167 | offset: offset, radius: radius, scaledRadius: radius / scale);
168 | }
169 |
170 | double _radius(double minValue, double maxValue, double dynamicValue) {
171 | double valueRange = maxValue - minValue;
172 | double p = ((dynamicValue - minValue) / valueRange);
173 | return minRadius + ((maxRadius - minRadius) * p);
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | /// Defines how a [MapFeature] should be painted on the map.
4 | abstract class Drawable {
5 | /// Gets the geometry bounds
6 | Rect getBounds();
7 |
8 | /// Draws this drawable on the canvas.
9 | void drawOn(Canvas canvas, Paint paint, double scale);
10 |
11 | /// Gets the count of points for this drawable.
12 | int get pointsCount;
13 |
14 | /// Checks whether a point is contained in this drawable.
15 | bool contains(Offset offset);
16 |
17 | /// Indicates whether it is visible.
18 | bool get visible;
19 |
20 | /// Indicates whether to draw the fill
21 | bool get hasFill;
22 | }
23 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_builder.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/rendering.dart';
2 | import 'package:vector_map/src/data/geometries.dart';
3 | import 'package:vector_map/src/data/map_data_source.dart';
4 | import 'package:vector_map/src/data/map_feature.dart';
5 | import 'package:vector_map/src/data/simplified_path.dart';
6 | import 'package:vector_map/src/drawable/drawable.dart';
7 | import 'package:vector_map/src/drawable/drawable_line.dart';
8 | import 'package:vector_map/src/drawable/drawable_polygon.dart';
9 | import 'package:vector_map/src/error.dart';
10 | import 'package:vector_map/src/simplifier.dart';
11 | import 'package:vector_map/src/theme/map_theme.dart';
12 |
13 | /// [Drawable] builder.
14 | class DrawableBuilder {
15 | static Drawable build(
16 | {required MapDataSource dataSource,
17 | required MapFeature feature,
18 | required MapTheme theme,
19 | required Matrix4 worldToCanvas,
20 | required double scale,
21 | required GeometrySimplifier simplifier}) {
22 | MapGeometry geometry = feature.geometry;
23 | if (geometry is MapPoint) {
24 | return _point(
25 | dataSource: dataSource,
26 | feature: feature,
27 | point: geometry,
28 | theme: theme,
29 | scale: scale,
30 | simplifier: simplifier);
31 | } else if (geometry is MapLinearRing) {
32 | return _linearRing(
33 | feature: feature,
34 | linearRing: geometry,
35 | theme: theme,
36 | worldToCanvas: worldToCanvas,
37 | simplifier: simplifier);
38 | } else if (geometry is MapLineString) {
39 | return _lineString(
40 | feature: feature,
41 | lineString: geometry,
42 | theme: theme,
43 | worldToCanvas: worldToCanvas,
44 | simplifier: simplifier);
45 | } else if (geometry is MapMultiLineString) {
46 | return _multiLineString(
47 | feature: feature,
48 | multiLineString: geometry,
49 | theme: theme,
50 | worldToCanvas: worldToCanvas,
51 | simplifier: simplifier);
52 | } else if (geometry is MapPolygon) {
53 | return _polygon(
54 | feature: feature,
55 | polygon: geometry,
56 | theme: theme,
57 | worldToCanvas: worldToCanvas,
58 | simplifier: simplifier);
59 | } else if (geometry is MapMultiPolygon) {
60 | return _multiPolygon(
61 | feature: feature,
62 | multiPolygon: geometry,
63 | theme: theme,
64 | worldToCanvas: worldToCanvas,
65 | simplifier: simplifier);
66 | } else {
67 | throw VectorMapError(
68 | 'Unrecognized geometry: ' + geometry.runtimeType.toString());
69 | }
70 | }
71 |
72 | static Drawable _point(
73 | {required MapDataSource dataSource,
74 | required MapFeature feature,
75 | required MapPoint point,
76 | required MapTheme theme,
77 | required double scale,
78 | required GeometrySimplifier simplifier}) {
79 | return theme.markerBuilder.build(
80 | dataSource: dataSource,
81 | feature: feature,
82 | offset: Offset(point.x, point.y),
83 | scale: scale);
84 | }
85 |
86 | static Drawable _lineString(
87 | {required MapFeature feature,
88 | required MapLineString lineString,
89 | required MapTheme theme,
90 | required Matrix4 worldToCanvas,
91 | required GeometrySimplifier simplifier}) {
92 | SimplifiedPath simplifiedPath =
93 | lineString.toSimplifiedPath(worldToCanvas, simplifier);
94 | return DrawableLine(simplifiedPath.path, simplifiedPath.pointsCount);
95 | }
96 |
97 | static Drawable _multiLineString(
98 | {required MapFeature feature,
99 | required MapMultiLineString multiLineString,
100 | required MapTheme theme,
101 | required Matrix4 worldToCanvas,
102 | required GeometrySimplifier simplifier}) {
103 | Path path = Path();
104 | int pointsCount = 0;
105 | for (MapLineString lineString in multiLineString.linesString) {
106 | SimplifiedPath simplifiedPath =
107 | lineString.toSimplifiedPath(worldToCanvas, simplifier);
108 | pointsCount += simplifiedPath.pointsCount;
109 | path.addPath(simplifiedPath.path, Offset.zero);
110 | }
111 | return DrawableLine(path, pointsCount);
112 | }
113 |
114 | static Drawable _linearRing(
115 | {required MapFeature feature,
116 | required MapLinearRing linearRing,
117 | required MapTheme theme,
118 | required Matrix4 worldToCanvas,
119 | required GeometrySimplifier simplifier}) {
120 | SimplifiedPath simplifiedPath =
121 | linearRing.toSimplifiedPath(worldToCanvas, simplifier);
122 | return DrawablePolygon(simplifiedPath.path, simplifiedPath.pointsCount);
123 | }
124 |
125 | static Drawable _polygon(
126 | {required MapFeature feature,
127 | required MapPolygon polygon,
128 | required MapTheme theme,
129 | required Matrix4 worldToCanvas,
130 | required GeometrySimplifier simplifier}) {
131 | SimplifiedPath simplifiedPath =
132 | polygon.toSimplifiedPath(worldToCanvas, simplifier);
133 | return DrawablePolygon(simplifiedPath.path, simplifiedPath.pointsCount);
134 | }
135 |
136 | static Drawable _multiPolygon(
137 | {required MapFeature feature,
138 | required MapMultiPolygon multiPolygon,
139 | required MapTheme theme,
140 | required Matrix4 worldToCanvas,
141 | required GeometrySimplifier simplifier}) {
142 | Path path = Path();
143 | int pointsCount = 0;
144 | for (MapPolygon polygon in multiPolygon.polygons) {
145 | SimplifiedPath simplifiedPath =
146 | polygon.toSimplifiedPath(worldToCanvas, simplifier);
147 | pointsCount += simplifiedPath.pointsCount;
148 | path.addPath(simplifiedPath.path, Offset.zero);
149 | }
150 | return DrawablePolygon(path, pointsCount);
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_feature.dart:
--------------------------------------------------------------------------------
1 | import 'package:vector_map/src/data/map_feature.dart';
2 | import 'package:vector_map/src/drawable/drawable.dart';
3 |
4 | class DrawableFeature {
5 | DrawableFeature(this.feature);
6 |
7 | final MapFeature feature;
8 | Drawable? drawable;
9 |
10 | @override
11 | bool operator ==(Object other) =>
12 | identical(this, other) ||
13 | other is DrawableFeature &&
14 | runtimeType == other.runtimeType &&
15 | feature == other.feature;
16 |
17 | @override
18 | int get hashCode => feature.hashCode;
19 | }
20 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_layer.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 | import 'dart:ui';
3 |
4 | import 'package:vector_map/src/data/map_feature.dart';
5 | import 'package:vector_map/src/data/map_layer.dart';
6 | import 'package:vector_map/src/drawable/drawable_layer_chunk.dart';
7 |
8 | /// Holds all geometry layers to be paint in the current resolution.
9 | class DrawableLayer {
10 | static const int pointsPerChunk = 35000;
11 |
12 | DrawableLayer._(this.layer, this.chunks);
13 |
14 | factory DrawableLayer(MapLayer layer) {
15 | List chunks = [];
16 | DrawableLayerChunk chunk = DrawableLayerChunk();
17 | for (MapFeature feature in layer.dataSource.features.values) {
18 | chunk.add(feature);
19 | if (chunk.pointsCount > pointsPerChunk) {
20 | chunks.add(chunk);
21 | chunk = DrawableLayerChunk();
22 | }
23 | }
24 | if (chunk.pointsCount > 0) {
25 | chunks.add(chunk);
26 | }
27 | return DrawableLayer._(layer, UnmodifiableListView(chunks));
28 | }
29 |
30 | final MapLayer layer;
31 | final UnmodifiableListView chunks;
32 |
33 | /// Gets the bounds of the layers. Returns [NULL] if the list is empty.
34 | static Rect? boundsOf(List drawableLayers) {
35 | Rect? bounds;
36 | for (DrawableLayer drawableLayer in drawableLayers) {
37 | Rect? layerBounds = drawableLayer.layer.dataSource.bounds;
38 | if (bounds == null) {
39 | bounds = layerBounds;
40 | } else if (layerBounds != null) {
41 | bounds = bounds.expandToInclude(layerBounds);
42 | }
43 | }
44 | return bounds;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_layer_chunk.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui' as ui;
2 |
3 | import 'package:vector_map/src/data/map_feature.dart';
4 | import 'package:vector_map/src/drawable/drawable_feature.dart';
5 |
6 | class DrawableLayerChunk {
7 | final List _drawableFeatures = [];
8 | ui.Image? buffer;
9 |
10 | ui.Rect? _bounds;
11 | ui.Rect? get bounds => _bounds;
12 |
13 | int _pointsCount = 0;
14 | int get pointsCount => _pointsCount;
15 |
16 | int get length => _drawableFeatures.length;
17 |
18 | DrawableFeature getDrawableFeature(int index) {
19 | return _drawableFeatures[index];
20 | }
21 |
22 | void add(MapFeature feature) {
23 | _drawableFeatures.add(DrawableFeature(feature));
24 | _pointsCount += feature.geometry.pointsCount;
25 |
26 | if (_bounds == null) {
27 | _bounds = feature.geometry.bounds;
28 | } else {
29 | _bounds = _bounds!.expandToInclude(feature.geometry.bounds);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_line.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:vector_map/src/drawable/drawable_path.dart';
4 |
5 | /// Defines a line or multi line to be painted on the map.
6 | class DrawableLine extends DrawablePath {
7 | DrawableLine(Path path, int pointsCount) : super(path, pointsCount);
8 |
9 | @override
10 | bool get hasFill => false;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_path.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:vector_map/src/drawable/drawable.dart';
4 |
5 | /// Defines a path to be painted on the map.
6 | abstract class DrawablePath extends Drawable {
7 | DrawablePath(Path path, int pointsCount)
8 | : this._path = path,
9 | this._pointsCount = pointsCount;
10 |
11 | final Path _path;
12 | final int _pointsCount;
13 |
14 | @override
15 | void drawOn(Canvas canvas, Paint paint, double scale) {
16 | canvas.drawPath(_path, paint);
17 | }
18 |
19 | @override
20 | Rect getBounds() {
21 | return _path.getBounds();
22 | }
23 |
24 | @override
25 | bool contains(Offset offset) {
26 | return _path.contains(offset);
27 | }
28 |
29 | @override
30 | int get pointsCount => _pointsCount;
31 |
32 | @override
33 | bool get visible => true;
34 | }
35 |
--------------------------------------------------------------------------------
/lib/src/drawable/drawable_polygon.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:vector_map/src/drawable/drawable_path.dart';
4 |
5 | /// Defines a polygon or multi polygon to be painted on the map.
6 | class DrawablePolygon extends DrawablePath {
7 | DrawablePolygon(Path path, int pointsCount) : super(path, pointsCount);
8 |
9 | @override
10 | bool get hasFill => true;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/src/drawable/marker.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:vector_map/src/data/map_data_source.dart';
4 | import 'package:vector_map/src/data/map_feature.dart';
5 | import 'package:vector_map/src/drawable/drawable.dart';
6 |
7 | /// [Marker] builder.
8 | abstract class MarkerBuilder {
9 | MarkerBuilder();
10 |
11 | /// Builds a [Marker]
12 | Marker build(
13 | {required MapDataSource dataSource,
14 | required MapFeature feature,
15 | required Offset offset,
16 | required double scale});
17 | }
18 |
19 | /// Defines a marker to be painted on the map.
20 | abstract class Marker extends Drawable {
21 | Marker({required this.offset});
22 |
23 | final Offset offset;
24 |
25 | @override
26 | void drawOn(Canvas canvas, Paint paint, double scale) {
27 | drawMarkerOn(canvas, paint, offset, scale);
28 | }
29 |
30 | @override
31 | int get pointsCount => 1;
32 |
33 | /// Draw this marker on [Canvas]
34 | void drawMarkerOn(Canvas canvas, Paint paint, Offset offset, double scale);
35 | }
36 |
--------------------------------------------------------------------------------
/lib/src/error.dart:
--------------------------------------------------------------------------------
1 | /// Generic [VectorMap] error
2 | class VectorMapError extends Error {
3 | final String _message;
4 |
5 | VectorMapError(this._message);
6 |
7 | VectorMapError.keyNotFound(String key)
8 | : this._message = 'Key "$key" not found.';
9 |
10 | VectorMapError.invalidType(String type)
11 | : this._message =
12 | 'Invalid "$type" type. Must be: FeatureCollection, GeometryCollection, Feature, Point, MultiPoint, LineString, MultiLineString, Polygon or MultiPolygon.';
13 |
14 | VectorMapError.invalidGeometryType(String type)
15 | : this._message =
16 | 'Invalid geometry "$type" type. Must be: GeometryCollection, Point, MultiPoint, LineString, MultiLineString, Polygon or MultiPolygon.';
17 |
18 | @override
19 | String toString() {
20 | return 'VectorMapError - $_message';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/src/low_quality_mode.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// The low-quality mode can be used during resizing, panning,
4 | /// and zooming to optimize the drawing.
5 | ///
6 | /// Allows you to simplify drawing during these events avoiding freezes.
7 | /// The default [quality] value is 0.3.
8 | class LowQualityMode {
9 | LowQualityMode(
10 | {this.quality = 0.3,
11 | this.strokeColor = Colors.black,
12 | this.fillEnabled = false}) {
13 | if (this.quality <= 0 || this.quality > 1) {
14 | throw ArgumentError(
15 | 'Quality value must be greater than 0 and less than or equal to 1');
16 | }
17 | }
18 |
19 | /// Defines the quality of the geometries that will be drawn during events.
20 | /// Value 1 represents 100% quality.
21 | final double quality;
22 |
23 | /// Color to paint the edge of geometries.
24 | /// If null, the color defined by the theme will be used.
25 | final Color? strokeColor;
26 |
27 | final bool fillEnabled;
28 | }
29 |
--------------------------------------------------------------------------------
/lib/src/map_highlight.dart:
--------------------------------------------------------------------------------
1 | import 'package:vector_map/src/data/map_feature.dart';
2 | import 'package:vector_map/src/drawable/drawable_feature.dart';
3 |
4 | /// Base class to define which [MapFeature] should be highlighted.
5 | abstract class MapHighlight {
6 | MapHighlight({required this.layerId});
7 |
8 | /// Identifier of the layer to be highlighted.
9 | final int layerId;
10 |
11 | /// Identifies whether the rule applies to a given [MapFeature].
12 | bool applies(MapFeature feature);
13 |
14 | @override
15 | bool operator ==(Object other) =>
16 | identical(this, other) ||
17 | other is MapHighlight &&
18 | runtimeType == other.runtimeType &&
19 | layerId == other.layerId;
20 |
21 | @override
22 | int get hashCode => layerId.hashCode;
23 | }
24 |
25 | /// Defines a single [MapFeature] to be highlighted.
26 | class MapSingleHighlight extends MapHighlight {
27 | MapSingleHighlight({required int layerId, this.drawableFeature})
28 | : super(layerId: layerId);
29 |
30 | final DrawableFeature? drawableFeature;
31 |
32 | @override
33 | bool applies(MapFeature feature) {
34 | return this.drawableFeature?.feature == feature;
35 | }
36 |
37 | @override
38 | bool operator ==(Object other) =>
39 | identical(this, other) ||
40 | super == other &&
41 | other is MapSingleHighlight &&
42 | runtimeType == other.runtimeType &&
43 | drawableFeature == other.drawableFeature;
44 |
45 | @override
46 | int get hashCode => super.hashCode ^ drawableFeature.hashCode;
47 | }
48 |
49 | /// Rule to find out which [MapFeature] should be highlighted.
50 | class MapGradientHighlight extends MapHighlight {
51 | /// Builds a [MapHighlight]
52 | ///
53 | /// The [rangePerPixel] is the range of value represented by each legend
54 | /// bar pixel, that is, the range between the min and the max values
55 | /// divided by the height of the legend bar.
56 | factory MapGradientHighlight(
57 | {required int layerId,
58 | required String key,
59 | required double value,
60 | required double rangePerPixel,
61 | required double max,
62 | required double min}) {
63 | int comparator = 0;
64 | double r = comparatorPrecisionPixels * rangePerPixel;
65 | if (value > max - r) {
66 | comparator = 1;
67 | } else if (value < min + r) {
68 | comparator = -1;
69 | }
70 | return MapGradientHighlight._(
71 | layerId: layerId,
72 | key: key,
73 | value: value,
74 | rangePerPixel: rangePerPixel,
75 | comparator: comparator);
76 | }
77 |
78 | /// Builds a [MapGradientHighlight]
79 | MapGradientHighlight._(
80 | {required int layerId,
81 | required this.key,
82 | required this.value,
83 | required this.rangePerPixel,
84 | required this.comparator})
85 | : super(layerId: layerId);
86 |
87 | final String key;
88 | final double value;
89 | final double rangePerPixel;
90 | final int comparator;
91 |
92 | static const int precisionPixels = 3;
93 | static const int comparatorPrecisionPixels = 2 * precisionPixels;
94 |
95 | /// Identifies whether the rule applies to a given [MapFeature].
96 | @override
97 | bool applies(MapFeature feature) {
98 | double? featureValue = feature.getDoubleValue(key);
99 | if (featureValue != null) {
100 | if (greater()) {
101 | return value < featureValue;
102 | } else if (smaller()) {
103 | return value > featureValue;
104 | } else {
105 | double r = rangePerPixel * precisionPixels;
106 | if (value - r <= featureValue && featureValue <= value + r) {
107 | return true;
108 | }
109 | }
110 | }
111 | return false;
112 | }
113 |
114 | /// Indicates whether to compare with larger values.
115 | bool greater() {
116 | return comparator == 1;
117 | }
118 |
119 | /// Indicates whether to compare with smaller values.
120 | bool smaller() {
121 | return comparator == -1;
122 | }
123 |
124 | String get formattedValue {
125 | if (greater()) {
126 | return '> ' + value.roundToDouble().toString();
127 | } else if (smaller()) {
128 | return '< ' + value.roundToDouble().toString();
129 | }
130 | return '≈ ' + value.roundToDouble().toString();
131 | }
132 |
133 | @override
134 | bool operator ==(Object other) =>
135 | identical(this, other) ||
136 | super == other &&
137 | other is MapGradientHighlight &&
138 | runtimeType == other.runtimeType &&
139 | key == other.key &&
140 | value == other.value &&
141 | rangePerPixel == other.rangePerPixel &&
142 | comparator == other.comparator;
143 |
144 | @override
145 | int get hashCode =>
146 | super.hashCode ^
147 | key.hashCode ^
148 | value.hashCode ^
149 | rangePerPixel.hashCode ^
150 | comparator.hashCode;
151 | }
152 |
--------------------------------------------------------------------------------
/lib/src/map_painter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:vector_map/src/data/map_data_source.dart';
4 | import 'package:vector_map/src/data/map_feature.dart';
5 | import 'package:vector_map/src/data/map_layer.dart';
6 | import 'package:vector_map/src/draw_utils.dart';
7 | import 'package:vector_map/src/drawable/drawable.dart';
8 | import 'package:vector_map/src/drawable/drawable_feature.dart';
9 | import 'package:vector_map/src/drawable/drawable_layer.dart';
10 | import 'package:vector_map/src/drawable/drawable_layer_chunk.dart';
11 | import 'package:vector_map/src/map_highlight.dart';
12 | import 'package:vector_map/src/theme/map_highlight_theme.dart';
13 | import 'package:vector_map/src/theme/map_theme.dart';
14 | import 'package:vector_map/src/vector_map_controller.dart';
15 |
16 | /// Painter for [VectorMap].
17 | class MapPainter extends CustomPainter {
18 | MapPainter({required this.controller});
19 | final VectorMapController controller;
20 |
21 | @override
22 | void paint(Canvas canvas, Size size) {
23 | MapHighlight? highlight = controller.highlight;
24 |
25 | DrawableLayer? overlayContourDrawableLayer;
26 |
27 | // drawing layers
28 | for (int layerIndex = 0;
29 | layerIndex < controller.layersCount;
30 | layerIndex++) {
31 | DrawableLayer drawableLayer = controller.getDrawableLayer(layerIndex);
32 | for (DrawableLayerChunk chunk in drawableLayer.chunks) {
33 | if (controller.drawBuffers && chunk.buffer != null) {
34 | canvas.drawImage(chunk.buffer!, Offset.zero, Paint());
35 | } else {
36 | // resizing, panning or zooming
37 | canvas.save();
38 | controller.applyMatrixOn(canvas);
39 | // drawing contour only to be faster
40 | DrawUtils.drawContour(
41 | canvas: canvas,
42 | chunk: chunk,
43 | layer: drawableLayer.layer,
44 | contourThickness: controller.contourThickness,
45 | scale: controller.scale,
46 | antiAlias: false);
47 | canvas.restore();
48 | }
49 | }
50 |
51 | MapLayer layer = drawableLayer.layer;
52 |
53 | // highlighting
54 | if (highlight != null &&
55 | highlight.layerId == layer.id &&
56 | layer.highlightTheme != null) {
57 | if (controller.contourThickness > 0 &&
58 | layer.highlightTheme!.overlayContour) {
59 | overlayContourDrawableLayer = drawableLayer;
60 | }
61 |
62 | canvas.save();
63 | controller.applyMatrixOn(canvas);
64 |
65 | if (layer.highlightTheme!.color != null) {
66 | var paint = Paint()
67 | ..style = PaintingStyle.fill
68 | ..color = layer.highlightTheme!.color!
69 | ..isAntiAlias = true;
70 | if (highlight is MapSingleHighlight) {
71 | DrawableFeature? drawableFeature = highlight.drawableFeature;
72 | Drawable? drawable = drawableFeature?.drawable;
73 | if (drawable != null && drawable.visible && drawable.hasFill) {
74 | drawable.drawOn(canvas, paint, controller.scale);
75 | }
76 | } else {
77 | DrawUtils.drawHighlight(
78 | canvas: canvas,
79 | drawableLayer: drawableLayer,
80 | paint: paint,
81 | scale: controller.scale,
82 | fillOnly: true,
83 | highlight: highlight);
84 | }
85 | }
86 |
87 | if (controller.contourThickness > 0 &&
88 | layer.highlightTheme!.overlayContour == false) {
89 | _drawHighlightContour(canvas, drawableLayer, controller);
90 | }
91 |
92 | canvas.restore();
93 | }
94 | }
95 |
96 | // drawing the overlay highlight contour
97 | if (overlayContourDrawableLayer != null) {
98 | canvas.save();
99 | controller.applyMatrixOn(canvas);
100 | _drawHighlightContour(canvas, overlayContourDrawableLayer, controller);
101 | canvas.restore();
102 | }
103 |
104 | // drawing labels
105 | for (int layerIndex = 0;
106 | layerIndex < controller.layersCount;
107 | layerIndex++) {
108 | DrawableLayer drawableLayer = controller.getDrawableLayer(layerIndex);
109 | MapLayer layer = drawableLayer.layer;
110 | MapDataSource dataSource = layer.dataSource;
111 | MapTheme theme = layer.theme;
112 | MapHighlightTheme? highlightTheme = layer.highlightTheme;
113 | if (theme.labelVisibility != null ||
114 | (highlightTheme != null && highlightTheme.labelVisibility != null)) {
115 | for (DrawableLayerChunk chunk in drawableLayer.chunks) {
116 | for (int index = 0; index < chunk.length; index++) {
117 | DrawableFeature drawableFeature = chunk.getDrawableFeature(index);
118 | MapFeature feature = drawableFeature.feature;
119 | Drawable? drawable = drawableFeature.drawable;
120 | if (drawable != null && drawable.visible && feature.label != null) {
121 | LabelVisibility? labelVisibility;
122 | if (highlight != null &&
123 | highlight.layerId == layer.id &&
124 | highlight.applies(feature) &&
125 | highlightTheme != null &&
126 | highlightTheme.labelVisibility != null) {
127 | labelVisibility = highlightTheme.labelVisibility;
128 | } else {
129 | labelVisibility = theme.labelVisibility;
130 | }
131 | if (labelVisibility != null && labelVisibility(feature)) {
132 | LabelStyleBuilder? labelStyleBuilder;
133 | MapHighlightTheme? highlightTheme;
134 | if (highlight != null && highlight.applies(feature)) {
135 | highlightTheme = layer.highlightTheme;
136 | if (highlightTheme != null) {
137 | labelStyleBuilder = highlightTheme.labelStyleBuilder;
138 | }
139 | }
140 | Color featureColor = MapTheme.getFeatureColor(
141 | dataSource, feature, theme, highlightTheme);
142 | if (labelStyleBuilder == null) {
143 | labelStyleBuilder = theme.labelStyleBuilder;
144 | }
145 | _drawLabel(
146 | canvas, feature, drawable, featureColor, labelStyleBuilder);
147 | }
148 | }
149 | }
150 | }
151 | }
152 | }
153 | }
154 |
155 | void _drawHighlightContour(Canvas canvas, DrawableLayer drawableLayer,
156 | VectorMapController controller) {
157 | MapHighlight? highlight = controller.highlight;
158 | Color? color = MapTheme.getContourColor(
159 | drawableLayer.layer.theme, drawableLayer.layer.highlightTheme);
160 | if (color != null) {
161 | var paint = Paint()
162 | ..style = PaintingStyle.stroke
163 | ..color = color
164 | ..strokeWidth = controller.contourThickness / controller.scale
165 | ..isAntiAlias = true;
166 | if (highlight is MapSingleHighlight) {
167 | DrawableFeature? drawableFeature = highlight.drawableFeature;
168 | Drawable? drawable = drawableFeature?.drawable;
169 | if (drawable != null && drawable.visible) {
170 | drawable.drawOn(canvas, paint, controller.scale);
171 | }
172 | } else {
173 | DrawUtils.drawHighlight(
174 | canvas: canvas,
175 | drawableLayer: drawableLayer,
176 | paint: paint,
177 | scale: controller.scale,
178 | fillOnly: false,
179 | highlight: highlight!);
180 | }
181 | }
182 | }
183 |
184 | void _drawLabel(Canvas canvas, MapFeature feature, Drawable drawable,
185 | Color featureColor, LabelStyleBuilder? labelStyleBuilder) {
186 | Color labelColor = _labelColorFrom(featureColor);
187 |
188 | TextStyle? labelStyle;
189 | if (labelStyleBuilder != null) {
190 | labelStyle = labelStyleBuilder(feature, featureColor, labelColor);
191 | }
192 | if (labelStyle == null) {
193 | labelStyle = TextStyle(
194 | color: labelColor,
195 | fontSize: 11,
196 | );
197 | }
198 |
199 | Rect bounds = MatrixUtils.transformRect(
200 | controller.worldToCanvas, drawable.getBounds());
201 | _drawText(canvas, bounds.center, feature.label!, labelStyle);
202 | }
203 |
204 | Color _labelColorFrom(Color featureColor) {
205 | final luminance = featureColor.computeLuminance();
206 | if (luminance > 0.55) {
207 | return const Color(0xFF000000);
208 | }
209 | return const Color(0xFFFFFFFF);
210 | }
211 |
212 | void _drawText(
213 | Canvas canvas, Offset center, String text, TextStyle textStyle) {
214 | TextSpan textSpan = TextSpan(
215 | text: text,
216 | style: textStyle,
217 | );
218 | TextPainter textPainter = TextPainter(
219 | text: textSpan,
220 | textDirection: TextDirection.ltr,
221 | );
222 |
223 | textPainter.layout(
224 | minWidth: 0,
225 | );
226 |
227 | double xCenter = center.dx - (textPainter.width / 2);
228 | double yCenter = center.dy - (textPainter.height / 2);
229 | textPainter.paint(canvas, Offset(xCenter, yCenter));
230 | }
231 |
232 | @override
233 | bool shouldRepaint(covariant CustomPainter oldDelegate) {
234 | return true;
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/lib/src/simplifier.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 |
3 | import 'package:flutter/rendering.dart';
4 | import 'package:vector_map/src/data/geometries.dart';
5 |
6 | /// Simplifies geometry by ignoring unnecessary points for viewing
7 | /// on the screen.
8 | abstract class GeometrySimplifier {
9 | GeometrySimplifier(this.tolerance);
10 |
11 | final double tolerance;
12 |
13 | List simplify(Matrix4 worldToCanvas, List points);
14 |
15 | MapPoint transformPoint(Matrix4 transform, MapPoint point) {
16 | final Float64List storage = transform.storage;
17 | final double x = point.x;
18 | final double y = point.y;
19 |
20 | // Directly simulate the transform of the vector (x, y, 0, 1),
21 | // dropping the resulting Z coordinate, and normalizing only
22 | // if needed.
23 |
24 | final double rx = storage[0] * x + storage[4] * y + storage[12];
25 | final double ry = storage[1] * x + storage[5] * y + storage[13];
26 | final double rw = storage[3] * x + storage[7] * y + storage[15];
27 | if (rw == 1.0) {
28 | return MapPoint(rx, ry);
29 | } else {
30 | return MapPoint(rx / rw, ry / rw);
31 | }
32 | }
33 | }
34 |
35 | /// Ignores points that collide on the same physical pixel.
36 | class IntegerSimplifier extends GeometrySimplifier {
37 | IntegerSimplifier({double tolerance = 1}) : super(tolerance);
38 |
39 | @override
40 | List simplify(Matrix4 worldToCanvas, List points) {
41 | List simplifiedPoints = [];
42 | MapPoint? lastMapPoint;
43 | for (MapPoint point in points) {
44 | MapPoint transformedPoint = transformPoint(worldToCanvas, point);
45 |
46 | transformedPoint = MapPoint(transformedPoint.x.truncateToDouble(),
47 | transformedPoint.y.truncateToDouble());
48 | if (simplifiedPoints.isEmpty ||
49 | _accept(lastMapPoint!, transformedPoint)) {
50 | simplifiedPoints.add(point);
51 | lastMapPoint = transformedPoint;
52 | }
53 | }
54 | return simplifiedPoints;
55 | }
56 |
57 | bool _accept(MapPoint p1, MapPoint p2) {
58 | double dx = (p1.x - p2.x).abs();
59 | if (dx >= tolerance) {
60 | return true;
61 | }
62 | double dy = (p1.y - p2.y).abs();
63 | return dy >= tolerance;
64 | }
65 | }
66 |
67 | /// Does not apply any simplification.
68 | class NoSimplifier extends GeometrySimplifier {
69 | NoSimplifier() : super(0);
70 |
71 | @override
72 | List simplify(Matrix4 worldToCanvas, List points) {
73 | return points;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/src/theme/map_gradient_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/rendering.dart';
2 | import 'package:vector_map/src/data/map_data_source.dart';
3 | import 'package:vector_map/src/data/map_feature.dart';
4 | import 'package:vector_map/src/data/property_limits.dart';
5 | import 'package:vector_map/src/drawable/marker.dart';
6 | import 'package:vector_map/src/error.dart';
7 | import 'package:vector_map/src/theme/map_theme.dart';
8 |
9 | /// Theme for gradient colors.
10 | ///
11 | /// The gradient is created given the colors and limit values of the
12 | /// chosen property.
13 | /// The property must have numeric values.
14 | /// If the [min] is set, all smaller values will be displayed with the first
15 | /// gradient color.
16 | /// If the [max] is set, all larger values will be displayed with the last
17 | /// gradient color.
18 | class MapGradientTheme extends MapTheme {
19 | MapGradientTheme(
20 | {Color? color,
21 | Color? contourColor,
22 | LabelVisibility? labelVisibility,
23 | LabelStyleBuilder? labelStyleBuilder,
24 | MarkerBuilder? markerBuilder,
25 | double? min,
26 | double? max,
27 | required this.key,
28 | required this.colors})
29 | : this._max = max,
30 | this._min = min,
31 | super(
32 | color: color,
33 | contourColor: contourColor,
34 | labelVisibility: labelVisibility,
35 | labelStyleBuilder: labelStyleBuilder,
36 | markerBuilder: markerBuilder) {
37 | if (colors.length < 2) {
38 | throw VectorMapError('At least 2 colors are required for the gradient.');
39 | }
40 | }
41 |
42 | final double? _min;
43 | final double? _max;
44 | final String key;
45 | final List colors;
46 |
47 | @override
48 | bool hasValue() {
49 | //It is not possible to know in advance, it depends on the property values.
50 | return true;
51 | }
52 |
53 | double? min(MapDataSource dataSource) {
54 | double? min = this._min;
55 | if (min == null) {
56 | PropertyLimits? propertyLimits = dataSource.getPropertyLimits(key);
57 | if (propertyLimits != null) {
58 | min = propertyLimits.min;
59 | }
60 | }
61 | return min;
62 | }
63 |
64 | double? max(MapDataSource dataSource) {
65 | double? max = this._max;
66 | if (max == null) {
67 | PropertyLimits? propertyLimits = dataSource.getPropertyLimits(key);
68 | if (propertyLimits != null) {
69 | max = propertyLimits.max;
70 | }
71 | }
72 | return max;
73 | }
74 |
75 | @override
76 | Color? getColor(MapDataSource dataSource, MapFeature feature) {
77 | double? min = this.min(dataSource);
78 | double? max = this.max(dataSource);
79 |
80 | if (min != null && max != null) {
81 | double? value = feature.getDoubleValue(key);
82 | if (value != null) {
83 | if (value <= min) {
84 | return colors.first;
85 | }
86 | if (value >= max) {
87 | return colors.last;
88 | }
89 |
90 | double size = max - min;
91 |
92 | int stepsCount = colors.length - 1;
93 | double stepSize = size / stepsCount;
94 | int stepIndex = (value - min) ~/ stepSize;
95 |
96 | double currentStepRange = (stepIndex * stepSize) + stepSize;
97 | double positionInStep = value - min - (stepIndex * stepSize);
98 | double t = positionInStep / currentStepRange;
99 | return Color.lerp(colors[stepIndex], colors[stepIndex + 1], t)!;
100 | }
101 | }
102 | return super.getColor(dataSource, feature);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/lib/src/theme/map_highlight_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vector_map/src/theme/map_theme.dart';
3 |
4 | /// The theme for highlights.
5 | ///
6 | /// This theme is activated by hover or external components like a legend.
7 | class MapHighlightTheme {
8 | /// Builds a [MapHighlightTheme]
9 | MapHighlightTheme(
10 | {this.color,
11 | this.contourColor,
12 | this.overlayContour = false,
13 | this.labelVisibility,
14 | this.labelStyleBuilder});
15 |
16 | final Color? color;
17 | final Color? contourColor;
18 | final bool overlayContour;
19 | final LabelVisibility? labelVisibility;
20 | final LabelStyleBuilder? labelStyleBuilder;
21 |
22 | /// Indicates whether the theme has any value set.
23 | bool hasValue() {
24 | return color != null || contourColor != null || labelVisibility != null;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/src/theme/map_rule_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/rendering.dart';
2 | import 'package:vector_map/src/data/map_data_source.dart';
3 | import 'package:vector_map/src/data/map_feature.dart';
4 | import 'package:vector_map/src/drawable/marker.dart';
5 | import 'package:vector_map/src/theme/map_theme.dart';
6 |
7 | /// Theme for colors by rule.
8 | ///
9 | /// The feature color is obtained from the first rule that returns
10 | /// a non-null color.
11 | /// If all rules return a null color, the default color is used.
12 | class MapRuleTheme extends MapTheme {
13 | MapRuleTheme(
14 | {Color? color,
15 | Color? contourColor,
16 | LabelVisibility? labelVisibility,
17 | LabelStyleBuilder? labelStyleBuilder,
18 | MarkerBuilder? markerBuilder,
19 | required List colorRules})
20 | : this._colorRules = colorRules,
21 | super(
22 | color: color,
23 | contourColor: contourColor,
24 | labelVisibility: labelVisibility,
25 | labelStyleBuilder: labelStyleBuilder,
26 | markerBuilder: markerBuilder);
27 |
28 | final List _colorRules;
29 |
30 | @override
31 | bool hasValue() {
32 | //It is not possible to know in advance, it depends on the rule.
33 | return true;
34 | }
35 |
36 | @override
37 | Color? getColor(MapDataSource dataSource, MapFeature feature) {
38 | Color? color;
39 | for (ColorRule rule in _colorRules) {
40 | color = rule(feature);
41 | if (color != null) {
42 | break;
43 | }
44 | }
45 | return color != null ? color : super.getColor(dataSource, feature);
46 | }
47 | }
48 |
49 | /// Rule to obtain a color of a feature.
50 | typedef ColorRule = Color? Function(MapFeature feature);
51 |
--------------------------------------------------------------------------------
/lib/src/theme/map_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vector_map/src/data/map_data_source.dart';
3 | import 'package:vector_map/src/data/map_feature.dart';
4 | import 'package:vector_map/src/drawable/circle_marker.dart';
5 | import 'package:vector_map/src/drawable/marker.dart';
6 | import 'package:vector_map/src/theme/map_highlight_theme.dart';
7 |
8 | /// The [VectorMap] theme.
9 | class MapTheme {
10 | static const Color defaultColor = Color(0xFFE0E0E0);
11 | static const Color defaultContourColor = Color(0xFF9E9E9E);
12 |
13 | static Color getThemeOrDefaultColor(
14 | MapDataSource dataSource, MapFeature feature, MapTheme theme) {
15 | Color? color = theme.getColor(dataSource, feature);
16 | if (color != null) {
17 | return color;
18 | }
19 | return MapTheme.defaultColor;
20 | }
21 |
22 | /// Gets the feature color.
23 | static Color getFeatureColor(MapDataSource dataSource, MapFeature feature,
24 | MapTheme theme, MapHighlightTheme? highlightTheme) {
25 | Color? color = highlightTheme?.color;
26 | if (color == null) {
27 | color = theme.getColor(dataSource, feature);
28 | }
29 | if (color != null) {
30 | return color;
31 | }
32 | return MapTheme.defaultColor;
33 | }
34 |
35 | /// Gets the feature contour color.
36 | static Color? getContourColor(
37 | MapTheme theme, MapHighlightTheme? highlightTheme) {
38 | Color? color = highlightTheme?.contourColor;
39 | if (color == null) {
40 | color = theme.contourColor;
41 | }
42 | return color;
43 | }
44 |
45 | /// Builds a [VectorMap]
46 | MapTheme(
47 | {Color? color,
48 | this.contourColor,
49 | this.labelVisibility,
50 | this.labelStyleBuilder,
51 | MarkerBuilder? markerBuilder})
52 | : this._color = color,
53 | this.markerBuilder =
54 | markerBuilder != null ? markerBuilder : CircleMakerBuilder.fixed();
55 |
56 | final Color? _color;
57 | final Color? contourColor;
58 | final LabelVisibility? labelVisibility;
59 | final LabelStyleBuilder? labelStyleBuilder;
60 | final MarkerBuilder markerBuilder;
61 |
62 | /// Indicates whether the theme has any value set.
63 | bool hasValue() {
64 | return _color != null || contourColor != null || labelVisibility != null;
65 | }
66 |
67 | /// Gets the feature color.
68 | Color? getColor(MapDataSource dataSource, MapFeature feature) {
69 | return _color;
70 | }
71 | }
72 |
73 | /// Defines the visibility of a [MapFeature]
74 | typedef LabelVisibility = bool Function(MapFeature feature);
75 |
76 | /// The label style builder.
77 | typedef LabelStyleBuilder = TextStyle Function(
78 | MapFeature feature, Color featureColor, Color labelColor);
79 |
--------------------------------------------------------------------------------
/lib/src/theme/map_value_theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/rendering.dart';
2 | import 'package:vector_map/src/data/map_data_source.dart';
3 | import 'package:vector_map/src/data/map_feature.dart';
4 | import 'package:vector_map/src/drawable/marker.dart';
5 | import 'package:vector_map/src/theme/map_theme.dart';
6 |
7 | /// Theme for colors by value.
8 | class MapValueTheme extends MapTheme {
9 | MapValueTheme(
10 | {Color? color,
11 | Color? contourColor,
12 | LabelVisibility? labelVisibility,
13 | LabelStyleBuilder? labelStyleBuilder,
14 | MarkerBuilder? markerBuilder,
15 | required this.key,
16 | Map? colors})
17 | : this._colors = colors,
18 | super(
19 | color: color,
20 | contourColor: contourColor,
21 | labelVisibility: labelVisibility,
22 | labelStyleBuilder: labelStyleBuilder,
23 | markerBuilder: markerBuilder);
24 |
25 | final String key;
26 | final Map? _colors;
27 |
28 | @override
29 | bool hasValue() {
30 | return (_colors != null && _colors!.isNotEmpty) || super.hasValue();
31 | }
32 |
33 | @override
34 | Color? getColor(MapDataSource dataSource, MapFeature feature) {
35 | if (_colors != null) {
36 | dynamic value = feature.getValue(key);
37 | if (value != null && _colors!.containsKey(value)) {
38 | return _colors![value]!;
39 | }
40 | }
41 | return super.getColor(dataSource, feature);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/src/vector_map.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/gestures.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:vector_map/src/addon/map_addon.dart';
4 | import 'package:vector_map/src/data/map_feature.dart';
5 | import 'package:vector_map/src/data/map_layer.dart';
6 | import 'package:vector_map/src/drawable/drawable.dart';
7 | import 'package:vector_map/src/drawable/drawable_feature.dart';
8 | import 'package:vector_map/src/drawable/drawable_layer.dart';
9 | import 'package:vector_map/src/drawable/drawable_layer_chunk.dart';
10 | import 'package:vector_map/src/low_quality_mode.dart';
11 | import 'package:vector_map/src/vector_map_controller.dart';
12 | import 'package:vector_map/src/map_highlight.dart';
13 | import 'package:vector_map/src/map_painter.dart';
14 | import 'package:vector_map/src/vector_map_mode.dart';
15 |
16 | /// Vector map widget.
17 | class VectorMap extends StatefulWidget {
18 | VectorMap(
19 | {Key? key,
20 | this.controller,
21 | this.color,
22 | this.borderColor = Colors.black54,
23 | this.borderThickness = 1,
24 | this.layersPadding = const EdgeInsets.all(8),
25 | this.hoverRule,
26 | this.hoverListener,
27 | this.clickListener,
28 | this.addons,
29 | this.placeHolder,
30 | this.lowQualityMode})
31 | : super(key: key);
32 |
33 | final VectorMapController? controller;
34 | final Color? color;
35 | final Color? borderColor;
36 | final double? borderThickness;
37 | final Widget? placeHolder;
38 | final EdgeInsetsGeometry? layersPadding;
39 | final HoverRule? hoverRule;
40 | final HoverListener? hoverListener;
41 | final FeatureClickListener? clickListener;
42 | final List? addons;
43 | final LowQualityMode? lowQualityMode;
44 |
45 | @override
46 | State createState() => _VectorMapState();
47 | }
48 |
49 | /// Holds the initial mouse location and matrix translate from the pan.
50 | class _PanZoom {
51 | _PanZoom(
52 | {required this.initialMouseLocation,
53 | required this.initialMapScale,
54 | required this.translateX,
55 | required this.translateY})
56 | : this.lastLocalPosition = initialMouseLocation;
57 |
58 | final double initialMapScale;
59 | final Offset initialMouseLocation;
60 | final translateX;
61 | final translateY;
62 | Offset lastLocalPosition;
63 | bool _rebuildSimplifiedGeometry = false;
64 | bool get rebuildSimplifiedGeometry => _rebuildSimplifiedGeometry;
65 |
66 | double newScale(
67 | {required double currentMapScale, required double mouseScale}) {
68 | if (mouseScale != 1) {
69 | double newScale = initialMapScale * mouseScale;
70 | double delta = (1 - (newScale / currentMapScale)).abs();
71 | if (delta > 0.05) {
72 | _rebuildSimplifiedGeometry = true;
73 | return newScale;
74 | }
75 | }
76 | return currentMapScale;
77 | }
78 | }
79 |
80 | /// [VectorMap] state.
81 | class _VectorMapState extends State {
82 | VectorMapController _controller = VectorMapController();
83 |
84 | _PanZoom? _panZoom;
85 |
86 | @override
87 | void initState() {
88 | super.initState();
89 | if (widget.controller != null) {
90 | _controller = widget.controller!;
91 | }
92 | _controller.addListener(_rebuild);
93 | }
94 |
95 | @override
96 | void didUpdateWidget(covariant VectorMap oldWidget) {
97 | super.didUpdateWidget(oldWidget);
98 | if (widget.controller != null &&
99 | widget.controller != oldWidget.controller) {
100 | _controller.removeListener(_rebuild);
101 | _controller = widget.controller!;
102 | _controller.addListener(_rebuild);
103 | }
104 | }
105 |
106 | @override
107 | void dispose() {
108 | _controller.removeListener(_rebuild);
109 | super.dispose();
110 | }
111 |
112 | void _rebuild() {
113 | setState(() {
114 | // rebuild
115 | });
116 | }
117 |
118 | bool get _onPanAndZoom => _panZoom != null;
119 |
120 | @override
121 | Widget build(BuildContext context) {
122 | Widget? content;
123 | if (_controller.hasLayer) {
124 | Widget mapCanvas = _buildMapCanvas();
125 | if (widget.addons != null) {
126 | List children = [LayoutId(id: 0, child: mapCanvas)];
127 | int count = 1;
128 | for (MapAddon addon in widget.addons!) {
129 | DrawableFeature? hover;
130 | if (_controller.highlight != null &&
131 | _controller.highlight is MapSingleHighlight) {
132 | hover =
133 | (_controller.highlight as MapSingleHighlight).drawableFeature;
134 | }
135 | children.add(LayoutId(
136 | id: count,
137 | child: addon.buildWidget(
138 | context: context,
139 | mapApi: _controller,
140 | hover: hover?.feature)));
141 | count++;
142 | }
143 | content = CustomMultiChildLayout(
144 | children: children, delegate: _VectorMapLayoutDelegate(count));
145 | } else {
146 | content = mapCanvas;
147 | }
148 | } else if (widget.placeHolder != null) {
149 | content = widget.placeHolder;
150 | }
151 |
152 | BoxBorder? border;
153 | if (widget.borderColor != null &&
154 | widget.borderThickness != null &&
155 | widget.borderThickness! > 0) {
156 | border = Border.all(
157 | color: widget.borderColor!, width: widget.borderThickness!);
158 | }
159 | Decoration? decoration;
160 | if (widget.color != null || border != null) {
161 | decoration = BoxDecoration(color: widget.color, border: border);
162 | }
163 |
164 | return Container(decoration: decoration, child: content);
165 | }
166 |
167 | /// Builds the canvas area
168 | Widget _buildMapCanvas() {
169 | Widget mapCanvas = LayoutBuilder(
170 | builder: (BuildContext context, BoxConstraints constraints) {
171 | if (constraints.maxWidth == 0 || constraints.maxHeight == 0) {
172 | return Container();
173 | }
174 | Size canvasSize = Size(constraints.maxWidth, constraints.maxHeight);
175 | _controller.setCanvasSize(canvasSize);
176 |
177 | return ClipRect(
178 | child: CustomPaint(
179 | painter: MapPainter(controller: _controller),
180 | child: Container()));
181 | });
182 |
183 | mapCanvas = MouseRegion(
184 | child: mapCanvas,
185 | onHover: (event) => _onHover(
186 | localPosition: event.localPosition,
187 | canvasToWorld: _controller.canvasToWorld),
188 | onExit: (event) {
189 | if (_controller.highlight != null) {
190 | _updateHover(null);
191 | }
192 | _controller.debugger?.updateMouseHover();
193 | },
194 | );
195 |
196 | mapCanvas = GestureDetector(
197 | child: mapCanvas,
198 | onTapDown: (details) => _onClick(
199 | localPosition: details.localPosition,
200 | canvasToWorld: _controller.canvasToWorld),
201 | onScaleStart: (details) {
202 | if (_controller.mode == VectorMapMode.panAndZoom) {
203 | if (_controller.highlight != null) {
204 | _updateHover(null);
205 | }
206 | _controller.notifyPanZoomMode(start: true);
207 | setState(() {
208 | _panZoom = _PanZoom(
209 | initialMouseLocation: details.localFocalPoint,
210 | initialMapScale: _controller.scale,
211 | translateX: _controller.translateX,
212 | translateY: _controller.translateY);
213 | });
214 | }
215 | },
216 | onScaleUpdate: (details) {
217 | if (_panZoom != null) {
218 | if (details.pointerCount == 1) {
219 | // pan only
220 | _panZoom!.lastLocalPosition = details.localFocalPoint;
221 | double diffX = _panZoom!.initialMouseLocation.dx -
222 | details.localFocalPoint.dx;
223 | double diffY = _panZoom!.initialMouseLocation.dy -
224 | details.localFocalPoint.dy;
225 | _controller.translate(
226 | _panZoom!.translateX - diffX, _panZoom!.translateY - diffY);
227 | } else if (details.pointerCount > 1) {
228 | // zoom
229 | double newScale = _panZoom!.newScale(
230 | currentMapScale: _controller.scale,
231 | mouseScale: details.scale);
232 | _controller.zoom(details.localFocalPoint, newScale);
233 | }
234 | }
235 | },
236 | onScaleEnd: (details) {
237 | if (_panZoom != null) {
238 | _controller.notifyPanZoomMode(
239 | start: false,
240 | rebuildSimplifiedGeometry: _panZoom!.rebuildSimplifiedGeometry);
241 | final Offset localPosition = _panZoom!.lastLocalPosition;
242 | setState(() {
243 | _panZoom = null;
244 | });
245 | _onHover(
246 | localPosition: localPosition,
247 | canvasToWorld: _controller.canvasToWorld);
248 | }
249 | });
250 |
251 | mapCanvas = Listener(
252 | child: mapCanvas,
253 | onPointerSignal: (event) {
254 | if (event is PointerScrollEvent &&
255 | _controller.mode == VectorMapMode.panAndZoom) {
256 | bool zoomIn = event.scrollDelta.dy < 0;
257 | _controller.zoomOnLocation(event.localPosition, zoomIn);
258 | }
259 | });
260 |
261 | return Container(child: mapCanvas, padding: widget.layersPadding);
262 | }
263 |
264 | /// Triggered when a pointer tap on the map.
265 | void _onClick(
266 | {required Offset localPosition, required Matrix4 canvasToWorld}) {
267 | if (widget.clickListener != null) {
268 | Offset worldCoordinate =
269 | MatrixUtils.transformPoint(canvasToWorld, localPosition);
270 | MapFeature? feature;
271 | for (int layerIndex = _controller.layersCount - 1;
272 | layerIndex >= 0;
273 | layerIndex--) {
274 | DrawableLayer drawableLayer = _controller.getDrawableLayer(layerIndex);
275 | DrawableFeature? drawableFeature =
276 | _findDrawableFeature(drawableLayer, worldCoordinate);
277 | if (drawableFeature != null) {
278 | feature = drawableFeature.feature;
279 | break;
280 | }
281 | }
282 | if (feature != null) {
283 | widget.clickListener!(feature);
284 | }
285 | }
286 | }
287 |
288 | /// Triggered when a pointer moves over the map.
289 | void _onHover(
290 | {required Offset localPosition, required Matrix4 canvasToWorld}) {
291 | if (_onPanAndZoom) {
292 | return;
293 | }
294 | Offset worldCoordinate =
295 | MatrixUtils.transformPoint(canvasToWorld, localPosition);
296 |
297 | _controller.debugger?.updateMouseHover(
298 | locationOnCanvas: localPosition, worldCoordinate: worldCoordinate);
299 |
300 | MapSingleHighlight? hoverHighlightRule;
301 | for (int layerIndex = _controller.layersCount - 1;
302 | layerIndex >= 0;
303 | layerIndex--) {
304 | DrawableLayer drawableLayer = _controller.getDrawableLayer(layerIndex);
305 | DrawableFeature? drawableFeature =
306 | _findDrawableFeature(drawableLayer, worldCoordinate);
307 | if (drawableFeature != null) {
308 | MapLayer layer = drawableLayer.layer;
309 | hoverHighlightRule = MapSingleHighlight(
310 | layerId: layer.id, drawableFeature: drawableFeature);
311 | break;
312 | }
313 | }
314 |
315 | if (_controller.highlight != hoverHighlightRule) {
316 | _updateHover(hoverHighlightRule);
317 | }
318 | }
319 |
320 | /// Finds the first feature that contains a coordinate.
321 | DrawableFeature? _findDrawableFeature(
322 | DrawableLayer drawableLayer, Offset worldCoordinate) {
323 | for (DrawableLayerChunk chunk in drawableLayer.chunks) {
324 | for (int index = 0; index < chunk.length; index++) {
325 | DrawableFeature drawableFeature = chunk.getDrawableFeature(index);
326 | MapFeature feature = drawableFeature.feature;
327 | if (widget.hoverRule != null && widget.hoverRule!(feature) == false) {
328 | continue;
329 | }
330 | Drawable? drawable = drawableFeature.drawable;
331 | if (drawable != null && drawable.contains(worldCoordinate)) {
332 | return drawableFeature;
333 | }
334 | }
335 | }
336 | return null;
337 | }
338 |
339 | void _updateHover(MapSingleHighlight? hoverHighlightRule) {
340 | if (hoverHighlightRule != null) {
341 | _controller.setHighlight(hoverHighlightRule);
342 | } else {
343 | _controller.clearHighlight();
344 | }
345 | if (widget.hoverListener != null) {
346 | widget.hoverListener!(hoverHighlightRule?.drawableFeature?.feature);
347 | }
348 | }
349 | }
350 |
351 | /// The [VectorMap] layout.
352 | class _VectorMapLayoutDelegate extends MultiChildLayoutDelegate {
353 | _VectorMapLayoutDelegate(this.count);
354 |
355 | final int count;
356 |
357 | @override
358 | void performLayout(Size size) {
359 | Size childSize = Size.zero;
360 | for (int id = 0; id < count; id++) {
361 | if (hasChild(id)) {
362 | if (id == 0) {
363 | childSize = layoutChild(id, BoxConstraints.tight(size));
364 | positionChild(id, Offset.zero);
365 | } else {
366 | childSize = layoutChild(id, BoxConstraints.loose(size));
367 | positionChild(
368 | id,
369 | Offset(size.width - childSize.width,
370 | size.height - childSize.height));
371 | }
372 | }
373 | }
374 | }
375 |
376 | @override
377 | bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
378 | return false;
379 | }
380 | }
381 |
382 | typedef FeatureClickListener = Function(MapFeature feature);
383 |
384 | typedef HoverRule = bool Function(MapFeature feature);
385 |
386 | typedef HoverListener = Function(MapFeature? feature);
387 |
--------------------------------------------------------------------------------
/lib/src/vector_map_api.dart:
--------------------------------------------------------------------------------
1 | import 'package:vector_map/src/map_highlight.dart';
2 |
3 | /// Defines the map API.
4 | /// Through this class, plugins and addons will be able to automate the map.
5 | abstract class VectorMapApi {
6 | /// Removes the current highlight.
7 | void clearHighlight();
8 |
9 | /// Sets a new highlight on the map.
10 | void setHighlight(MapHighlight newHighlight);
11 | }
12 |
--------------------------------------------------------------------------------
/lib/src/vector_map_mode.dart:
--------------------------------------------------------------------------------
1 | /// Indicates in which interaction mode the map is working.
2 | enum VectorMapMode { autoFit, panAndZoom }
3 |
--------------------------------------------------------------------------------
/lib/vector_map.dart:
--------------------------------------------------------------------------------
1 | library vector_map;
2 |
3 | export 'src/data_reader.dart';
4 | export 'src/data/map_data_source.dart';
5 | export 'src/data/geometries.dart';
6 | export 'src/data/map_feature.dart';
7 | export 'src/data/simplified_path.dart';
8 | export 'src/data/property_limits.dart';
9 | export 'src/error.dart';
10 | export 'src/drawable/drawable_builder.dart';
11 | export 'src/drawable/drawable.dart';
12 | export 'src/drawable/drawable_feature.dart';
13 | export 'src/drawable/drawable_path.dart';
14 | export 'src/drawable/drawable_polygon.dart';
15 | export 'src/drawable/drawable_line.dart';
16 | export 'src/drawable/drawable_layer.dart';
17 | export 'src/drawable/drawable_layer_chunk.dart';
18 | export 'src/drawable/marker.dart';
19 | export 'src/drawable/circle_marker.dart';
20 | export 'src/data/map_layer.dart';
21 | export 'src/debugger.dart';
22 | export 'src/addon/map_addon.dart';
23 | export 'src/addon/legend/legend.dart';
24 | export 'src/addon/legend/gradient_legend.dart';
25 | export 'src/simplifier.dart';
26 | export 'src/map_highlight.dart';
27 | export 'src/theme/map_theme.dart';
28 | export 'src/theme/map_value_theme.dart';
29 | export 'src/theme/map_rule_theme.dart';
30 | export 'src/theme/map_gradient_theme.dart';
31 | export 'src/theme/map_highlight_theme.dart';
32 | export 'src/vector_map_api.dart';
33 | export 'src/vector_map_mode.dart';
34 | export 'src/low_quality_mode.dart';
35 | export 'src/vector_map_controller.dart';
36 | export 'src/vector_map.dart';
37 |
--------------------------------------------------------------------------------
/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.8.2"
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.0"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.3.1"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.15.0"
46 | fake_async:
47 | dependency: transitive
48 | description:
49 | name: fake_async
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.2.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.3"
77 | meta:
78 | dependency: "direct main"
79 | description:
80 | name: meta
81 | url: "https://pub.dartlang.org"
82 | source: hosted
83 | version: "1.7.0"
84 | path:
85 | dependency: transitive
86 | description:
87 | name: path
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "1.8.0"
91 | sky_engine:
92 | dependency: transitive
93 | description: flutter
94 | source: sdk
95 | version: "0.0.99"
96 | source_span:
97 | dependency: transitive
98 | description:
99 | name: source_span
100 | url: "https://pub.dartlang.org"
101 | source: hosted
102 | version: "1.8.1"
103 | stack_trace:
104 | dependency: transitive
105 | description:
106 | name: stack_trace
107 | url: "https://pub.dartlang.org"
108 | source: hosted
109 | version: "1.10.0"
110 | stream_channel:
111 | dependency: transitive
112 | description:
113 | name: stream_channel
114 | url: "https://pub.dartlang.org"
115 | source: hosted
116 | version: "2.1.0"
117 | string_scanner:
118 | dependency: transitive
119 | description:
120 | name: string_scanner
121 | url: "https://pub.dartlang.org"
122 | source: hosted
123 | version: "1.1.0"
124 | term_glyph:
125 | dependency: transitive
126 | description:
127 | name: term_glyph
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "1.2.0"
131 | test_api:
132 | dependency: transitive
133 | description:
134 | name: test_api
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "0.4.8"
138 | typed_data:
139 | dependency: transitive
140 | description:
141 | name: typed_data
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "1.3.0"
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.1"
152 | sdks:
153 | dart: ">=2.14.0 <3.0.0"
154 | flutter: ">=1.17.0"
155 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: vector_map
2 | description: Vector map for Flutter. Highly customizable. Compatible with GeoJSON. Map chart. Pure Flutter.
3 | version: 0.7.0
4 | repository: https://github.com/caduandrade/vector_map_flutter
5 |
6 | environment:
7 | sdk: ">=2.12.0 <3.0.0"
8 | flutter: ">=1.17.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | meta: ^1.7.0
14 |
15 | dev_dependencies:
16 | flutter_test:
17 | sdk: flutter
18 |
19 | # For information on the generic Dart part of this file, see the
20 | # following page: https://dart.dev/tools/pub/pubspec
21 |
22 | # The following section is specific to Flutter.
23 | flutter:
24 | # To add assets to your package, add an assets section, like this:
25 | # assets:
26 | # - images/a_dot_ham.jpeg
27 | #
28 | # For details regarding assets in packages, see
29 | # https://flutter.dev/assets-and-images/#from-packages
30 | #
31 | # An image asset can refer to one or more resolution-specific "variants", see
32 | # https://flutter.dev/assets-and-images/#resolution-aware.
33 |
34 | # To add custom fonts to your package, add a fonts section here,
35 | # in this "flutter" section. Each entry in this list should have a
36 | # "family" key with the font family name, and a "fonts" key with a
37 | # list giving the asset and other descriptors for the font. For
38 | # example:
39 | # fonts:
40 | # - family: Schyler
41 | # fonts:
42 | # - asset: fonts/Schyler-Regular.ttf
43 | # - asset: fonts/Schyler-Italic.ttf
44 | # style: italic
45 | # - family: Trajan Pro
46 | # fonts:
47 | # - asset: fonts/TrajanPro.ttf
48 | # - asset: fonts/TrajanPro_Bold.ttf
49 | # weight: 700
50 | #
51 | # For details regarding fonts in packages, see
52 | # https://flutter.dev/custom-fonts/#from-packages
53 |
--------------------------------------------------------------------------------