Running_page: Make Your Own Running Home Page

Running page

Create a personal running home page 

demo

English | 简体中文 | Wiki

Runner's Page Show

Running page runners

RunnerpageApp
zhubao315https://zhubao315.github.io/runningStrava
shaonianchehttps://run.duanfei.orgStrava
yihong0618https://yihong.runNike
superleeyomhttps://running.leeyom.topNike
geekpluxhttps://activities.geekplux.comNike
guanlanhttps://grun.vercel.appStrava
tuzimoehttps://run.tuzi.moeNike
ben_29https://running.ben29.xyzStrava
kcllfhttps://running-tau.vercel.appGarmin-cn
mqhttps://running-iota.vercel.appKeep
zhaohongxuanhttps://running-page-psi.vercel.appKeep
yvetterowehttps://run.haoluo.ioStrava
love-exercisehttps://run.kai666666.topKeep
zstone12https://running-page.zstone12.vercel.appKeep
Laxhttps://lax.github.io/runningKeep
lusuzihttps://running.lusuzi.vercel.appNike
wh1994https://run4life.funGarmin
liuyihuihttps://run.foolishfox.cnKeep
sunyunxianhttps://sunyunxian.github.io/running_pageStrava
AhianZhanghttps://running.ahianzhang.comNike
L1cardohttps://run.licardo.cnNike
luckylele666https://0000928.xyzStrava
MFYDevhttps://mfydev.runGarmin-cn
Eishedhttps://run.iknow.funKeep
Liuxinhttps://liuxin.runNike
loucxhttps://loucx.github.io/runningNike
winf42https://winf42.github.ioGarmin-cn
sun0225SUNhttps://run.sunguoqi.comNike
Zhanhttps://run.zlog.inNike
Dennishttps://run.domon.cnGarmin-cn
hanpeihttps://running.nexts.topGarmin-cn
liugezhouhttps://run.liugezhou.onlineStrava
Jason Tanhttps://jason-cqtan.github.io/running_pageNike
Congehttps://conge.github.io/running_pageStrava
zHElEARNhttps://workouts.zhelearn.comStrava
Ym9ihttps://bobrun.vercel.app/Strava
jianchengwanghttps://jianchengwang.github.io/running_pageSuunto
fxbinhttps://fxbin.github.io/sport-records/Keep
shensl4499https://waner.runcodoon

How it works

image

Features

  1. GitHub Actions manages automatic synchronization of runs and generation of new pages.
  2. Gatsby-generated static pages, fast
  3. Support for Vercel (recommended) and GitHub Pages automated deployment
  4. React Hooks
  5. Mapbox for map display
  6. Supports most sports apps such as nike strava...

automatically backup gpx data for easy backup and uploading to other software.
Note: If you don't want to make the data public, you can choose strava's fuzzy processing, or private repositories.

Download

Clone or fork the repo.

git clone https://github.com/yihong0618/running_page.git --depth=1

Installation and testing (node >= 12 and <= 14 python >= 3.7)

pip3 install -r requirements.txt
yarn install
yarn develop

Open your browser and visit http://localhost:8000/

Docker

#build
# NRC
docker build -t running_page:latest . --build-arg app=NRC --build-arg nike_refresh_token=""
# Garmin
docker build -t running_page:latest . --build-arg app=Garmin --build-arg email=""  --build-arg password="" 
# Garmin-CN
docker build -t running_page:latest . --build-arg app=Garmin-CN --build-arg email=""  --build-arg password="" 
# Strava
docker build -t running_page:latest . --build-arg app=Strava --build-arg client_id=""  --build-arg client_secret=""  --build-arg refresch_token="" 
#Nike_to_Strava
docker build -t running_page:latest . --build-arg app=Nike_to_Strava  --build-arg nike_refresh_token="" --build-arg client_id=""  --build-arg client_secret=""  --build-arg refresch_token="" 

#run
docker run -itd -p 80:80   running_page:latest

#visit
Open your browser and visit localhost:80

Local sync data

Modifying Mapbox token in src/utils/const.js

If you use English please change IS_CHINESE = false in src/utils/const.js 
Suggested changes to your own Mapbox token

const MAPBOX_TOKEN =
  'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';

Custom your page

  • Find gatsby-config.js in the repository directory, find the following content, and change it to what you want.
siteMetadata: {
  siteTitle: 'Running Page', #website title
  siteUrl: 'https://yihong.run', #website url
  logo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTtc69JxHNcmN1ETpMUX4dozAgAN6iPjWalQ&usqp=CAU', #logo img
  description: 'Personal site and blog',
  navLinks: [
    {
      name: 'Blog', #navigation name
      url: 'https://yihong.run/running', #navigation url
    },
    {
      name: 'About',
      url: 'https://github.com/yihong0618/running_page/blob/master/README-CN.md',
    },
  ],
},
  • Modifying styling in src/utils/const.js
// styling: set to `false` if you want to disable dash-line route
const USE_DASH_LINE = true;
// styling: route line opacity: [0, 1]
const LINE_OPACITY = 0.4;

Download your running data and do not forget to generate svg in total page

GPX

Make your GPX data

Copy all your gpx files to GPX_OUT or new gpx files

python3(python) scripts/gpx_sync.py

TCX

Make your TCX data

Copy all your tcx files to TCX_OUT or new tcx files

python3(python) scripts/tcx_sync.py

Garmin

Get your Garmin data
If you only want to sync `type running` add args --only-run If you only want `tcx` files add args --tcx

python3(python) scripts/garmin_sync.py ${your email} ${your password}

example:

python3(python) scripts/garmin_sync.py example@gmail.com example

only-run:

python3(python) scripts/garmin_sync.py example@gmail.com example --only-run

Garmin-CN(China)

Get your Garmin-CN data
If you only want to sync `type running` add args --only-run If you only want `tcx` files add args --tcx

python3(python) scripts/garmin_sync.py ${your email} ${your password} --is-cn

example:

python3(python) scripts/garmin_sync.py example@gmail.com example --is-cn

Nike Run Club

Get your Nike Run Club data

Please note: When you choose to deploy running_page on your own server, due to Nike has blocked some IDC's IP band, maybe your server cannot sync Nike Run Club's data correctly and display 403 error, then you have to change another way to host it.

Get Nike's refresh_token

  1. Login Nike website
  2. In Develop -> Application-> Storage -> https:unite.nike.com look for refresh_token
     

image

  • Execute in the root directory:
python3(python) scripts/nike_sync.py ${nike refresh_token}

example:

python3(python) scripts/nike_sync.py eyJhbGciThiMTItNGIw******

example img

Strava

Get your Strava data

Sign in/Sign up Strava account

Open after successful Signin Strava Developers -> Create & Manage Your App

Create My API Application: Enter the following information

My API Application

Created successfully:

  • Use the link below to request all permissions: Replace ${your_id} in the link with My API Application Client ID
https://www.strava.com/oauth/authorize?client_id=${your_id}&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write

get_all_permissions

  • Get the code value in the link

example:

http://localhost/exchange_token?state=&code=1dab37edd9970971fb502c9efdd087f4f3471e6e&scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all

code value:

1dab37edd9970971fb502c9efdd087f4f3471e6

get_code

  • Use Client_idClient_secretCode get refresch_token: Execute in Terminal/iTerm
curl -X POST https://www.strava.com/oauth/token \
-F client_id=${Your Client ID} \
-F client_secret=${Your Client Secret} \
-F code=${Your Code} \
-F grant_type=authorization_code

example:

curl -X POST https://www.strava.com/oauth/token \
-F client_id=12345 \
-F client_secret=b21******d0bfb377998ed1ac3b0 \
-F code=d09******b58abface48003 \
-F grant_type=authorization_code

get_refresch_token

  • Sync Strava data
python3(python) scripts/strava_sync.py ${client_id} ${client_secret} ${refresch_token}

References:

TCX_to_Strava

upload all tcx files to strava
 

  1. follow the strava steps
  2. copy all your tcx files to TCX_OUT
  3. Execute in the root directory:
python3(python) scripts/tcx_to_strava_sync.py ${client_id} ${client_secret}  ${strava_refresch_token}

example:

python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx
or
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx --all
  • if you want to all files add args --all

GPX_to_Strava

upload all gpx files to strava
 

  1. follow the strava steps
  2. copy all your gpx files to GPX_OUT
  3. Execute in the root directory:
python3(python) scripts/gpx_to_strava_sync.py ${client_id} ${client_secret}  ${strava_refresch_token}

example:

python3(python) scripts/gpx_to_strava_sync.py xxx xxx xxx
or
python3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx --all
  • if you want to all files add args --all

Nike_to_Strava

Get your Nike Run Club data and upload to strava
 

  1. follow the nike and strava steps
  2. Execute in the root directory:
python3(python) scripts/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresch_token}

example:

python3(python) scripts/nike_to_strava_sync.py eyJhbGciThiMTItNGIw******  xxx xxx xxx

Garmin_to_Strava

Get your Garmin data and upload to strava
 

  1. finish garmin and strava setps
  2. Execute in the root directory:
python3(python) scripts/garmin_to_strava_sync.py  ${client_id} ${client_secret} ${strava_refresch_token} ${garmin_email} ${garmin_password} --is-cn

e.g.

python3(python) scripts/garmin_to_strava_sync.py  xxx xxx xxx xx xxx

Strava_to_Garmin

Get your Strava data and upload to Garmin
 

  1. finish garmin and strava setps, at the same time, you need to add additional strava config in Github Actions secret: secrets.STRAVA_EMAILsecrets.STRAVA_PASSWORD
  2. Execute in the root directory:
python3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}

if your garmin account region is China, you need to execute the command:

python3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --is-cn

ps: when initializing for the first time, if you have a large amount of strava data, some data may fail to upload, just retry several times.

Total Data Analysis

Running data display
 

python scripts/gen_svg.py --from-db --title "${{ env.TITLE }}" --type github --athlete "${{ env.ATHLETE }}" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github.svg --use-localtime --min-distance 0.5
python scripts/gen_svg.py --from-db --title "${{ env.TITLE_GRID }}" --type grid --athlete "${{ env.ATHLETE }}"  --output assets/grid.svg --min-distance 10.0 --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime

Generate year circular svg show

python3(python) scripts/gen_svg.py --from-db --type circular --use-localtime

For more display effects, see: https://github.com/flopp/GpxTrackPoster

server(recommendation vercel)

Use Vercel to deploy
 

  • vercel connects to your GitHub repo.


 

image

  • import repo


 

image

  1. Awaiting completion of deployment
  2. Visits

Use Cloudflare to deploy
 

Click Create a project in Pages to connect to your Repo.

After clicking Begin setup, modify Project's Build settings.

Select Framework preset to Gatsby

Scroll down, click Environment variables, then variable below:

Variable name = PYTHON_VERSION, Value = 3.7

Click Save and Deploy

Deploy to GitHub Pages

If you are using a custom domain for GitHub Pages, open .github/workflows/gh-pages.yml, change fqdn value to the domain name of your site.

(Skip this step if you're NOT using a custom domain) Modify gatsby-config.js, change pathPrefix value to the root path. If the repository name is running_page, the value will be /running_page.

Go to repository's Actions -> Workflows -> All Workflows, choose Publish GitHub Pages from the left panel, click Run workflow. Make sure the workflow runs without errors, and gh-pages branch is created.

Go to repository's Settings -> GitHub Pages -> Source, choose Branch: gh-pages, click Save.

GitHub Actions

Modifying information in GitHub Actions 
 

Actions source code The following steps need to be taken

  • change to your app type and info
     

image

  • Add your secret in repo Settings > Secrets (add only the ones you need).


 

image

  • My secret is as follows
     

image

  • Go to repository's Settings -> Code and automation -> Actions ->General, Scroll to the bottom, find Workflow permissions, choose the first option Read and write permissions, click Save.

TODO

  •  Complete this document.
  •  Support Garmin, Garmin China
  •  support for nike+strava
  •  Support English
  •  Refine the code
  •  add new features
  •  tests
  •  support the world map
  •  support multiple types, like hiking, biking~

Contribution

  • Any Issues PR welcome.
  • You can PR share your Running page in README I will merge it.

Before submitting PR:

  • Format Python code with black (black .)

Special thanks

Recommended Forks

Support

Just enjoy it~

FAQ

Strava Api limit

https://www.strava.com/settings/api https://developers.strava.com/docs/#rate-limiting

Strava API Rate Limit Exceeded. Retry after 100 seconds
Strava API Rate Limit Timeout. Retry in 799.491622 seconds

注:如果是之前 clone 或 Fork 的朋友 vercel 显示 404 可能需要更新下代码


Download Details:

Author: yihong0618
Source Code: https://github.com/yihong0618/running_page 
License: MIT license

#python #datavisualization #dataanalysis #mapbox 

Running_page: Make Your Own Running Home Page

How to Real-Time Location Changes with MongoDB Realm, Change Streams

When it comes to modern web applications, interactions often need to be done in real-time. This means that instead of periodically checking in for changes, watching or listening for changes often makes more sense.

Take the example of tracking something on a map. When it comes to package shipments, device tracking, or anything else where you need to know the real-time location, watching for those changes in location is great. Imagine needing to know where your fleet is so that you can dispatch them to a nearby incident?

When it comes to MongoDB, watching for changes can be done through change streams. These change streams can be used in any of the drivers, including front-end applications with MongoDB Realm.

In this tutorial, we’re going to leverage MongoDB Realm change streams. When the location data in our NoSQL documents change, we’re going to update the information on an interactive map powered by Mapbox.

Take the following animated image for example:

Mapbox Updates with MongoDB Change Streams

Rather than building an Internet of Things (IoT) device to track and submit GPS data, we’re going to simulate the experience by directly changing our documents in MongoDB. When the update operations are complete, the front-end application with the interactive map is watching for those changes and responding appropriately.

The Requirements

To be successful with this example, you’ll need to have a few things ready to go prior:

  • A MongoDB Atlas cluster
  • A MongoDB Realm application
  • A Mapbox account

For this example, the data will exist in MongoDB Atlas. Since we’re planning on interacting with our data using a front-end application, we’ll be using MongoDB Realm. A Realm application should be created within the MongoDB Cloud and connected to the MongoDB Atlas cluster prior to exploring this tutorial.

Get started with MongoDB Atlas and Realm for FREE in the MongoDB Cloud.

Mapbox will be used as our interactive map. Since Mapbox is a service, you’ll need to have created an account and have access to your access token.

In the animated image, I’m using the MongoDB Visual Studio Code plugin for interacting with the documents in my collection. You can do the same or use another tool such as Compass, the CLI, or the data explorer within Atlas to get the job done.

Understanding the Document Model for the Location Tracking Example

Because we’re only planning on moving a marker around on a map, the data model that we use doesn’t need to be extravagant. For this example, the following is more than acceptable:

{
    "_id": "5ec44f70fa59d66ba0dd93ae",
    "coordinates": [
        -121.4252,
        37.7397
    ],
    "username": "nraboy"
}

In the above example, the coordinates array has the first item representing the longitude and the second item representing the latitude. We’re including a username to show that we are going to watch for changes based on a particular document field. In a polished application, all users probably wouldn’t be watching for changes for all documents. Instead they’d probably be watching for changes of documents that belong to them.

While we could put authorization rules in place for users to access certain documents, it is out of the scope of this example. Instead, we’re going to mock it.

Building a Real-Time Location Tracking Application with Mapbox and the Realm SDK

Now we’re going to build our client-facing application which consists of Mapbox, some basic HTML and JavaScript, and MongoDB Realm.

Let’s start by adding the following boilerplate code:

<!DOCTYPE html>
<head>
    <script src="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.js"></script>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.css" rel="stylesheet" />
    <script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4.6.0/stitch.js"></script>
</head>
<html>
    <body style="margin: 0">
        <div id="map" style="width: 100vw; height: 100vh"></div>
        <script>
            // Logic here ...
        </script>
    </body>
</html>

The above code sets us up by including the Mapbox and MongoDB Realm SDKs. When it comes to querying MongoDB and interacting with the map, we’re going to be doing that from within the <script> tags.

Within the <script> tags, let’s get started by adding the following:

const client = stitch.Stitch.initializeDefaultAppClient('REALM_APP_ID_HERE');
const db = client.getServiceClient(stitch.RemoteMongoClient.factory, "mongodb-atlas").db("location_services");
mapboxgl.accessToken = "MAPBOX_ACCESS_TOKEN_HERE";

var currentLocationMarker;

The above lines of code are useful for the initialization of our services. You’ll want to swap the app id with your actual Realm app id and the Mapbox access token with your actual Mapbox access token. Both of these can be found within each of the services dashboards.

For this example, I’m going to assume you’re using a location_services database within MongoDB Atlas and a tracking collection within that database.

The currentLocationMarker variable will represent our changing marker that moves around on the map as new data comes in from the MongoDB change stream.

Within the same <script> tags, we can initialize the map for displaying:

let map = new mapboxgl.Map({
    container: "map",
    style: "mapbox://styles/mapbox/streets-v11",
    center: [-121.4252, 37.7397],
    zoom: 9
});

Since the map tiles that compose the map come from a service, we need to wait until the map is ready before we start interacting with it. We can make use of the Mapbox load event to let us know the map is ready:

map.on("load", async () => {
    await client.auth.loginWithCredential(new stitch.AnonymousCredential());
    let currentLocation = (await db.collection("tracking").findOne({ "username": "nraboy" })).coordinates;
    currentLocationMarker = new mapboxgl.Marker().setLngLat(currentLocation).addTo(map);
    const stream = await db.collection("tracking").watch({
        "fullDocument.username": "nraboy"
    });
    stream.onNext(event => {
        currentLocationMarker.setLngLat(event.fullDocument.coordinates);
    });
});

Inside the load event, we are doing anonymous authentication with MongoDB Realm. Remember, we could very easily use a stronger authentication method and have authorization rules, but for this example it’s out of the scope.

Once we’re authenticated to Realm, we execute a findOne operation based on the mock username field on our document. The only data we care about is the coordinates, but we want to make sure it comes from the correct username field.

With the latitude and longitude coordinate information in hand, we can update the marker position.

Up until now, we are just setting the marker to the last known position. This is because when we start watching with a change stream, we won’t receive an initial document. This is why we are doing the findOne first.

This brings us to the change stream:

const stream = await db.collection("tracking").watch({
    "fullDocument.username": "nraboy"
});
stream.onNext(event => {
    currentLocationMarker.setLngLat(event.fullDocument.coordinates);
});

For this particular change stream, we are only watching for documents where the username field matches. In a more polished and realistic example, you could use this to watch for only your own documents. We’re mocking this by hard-coding the value.

When documents with the username field experience some kind of change within Atlas, the marker location will update. This is done without us having to constantly query for updates based on a timer.

Conclusion

You just saw how to use change streams in a client-facing application using the MongoDB Realm SDK. To make our example more attractive, we went with a location tracking scenario, whereas when latitude and longitude locations change in the database, the positions are updated in real-time on a map powered by Mapbox.

If you’d like to give MongoDB Atlas and MongoDB Realm a try, there’s a forever FREE tier available through the MongoDB Cloud.

When it comes to location data and MongoDB, there’s so much more you can do. If you’d like to learn how to create and manage geofences, check out my previous tutorial titled, Location Geofencing with MongoDB, Realm, and Mapbox.

This content first appeared on MongoDB.

Original article source at: https://developer.mongodb.com/

#mongodb #stream #mapbox #nosql 

How to Real-Time Location Changes with MongoDB Realm, Change Streams

How to Location Geofencing with MongoDB, Stitch, and Mapbox

For a lot of organizations, when it comes to location, geofencing is often a very desirable or required feature. In case you’re unfamiliar, a geofence can be thought of as a virtual perimeter for a geographic area. Often, you’ll want to know when something enters or exits that geofence so that you can apply your own business logic. Such logic might include sending a notification or updating something in your database.

MongoDB supports GeoJSON data and offers quite a few operators that make working the location data easy.

When it comes to geofencing, why would you want to use a database like MongoDB rather than defining boundaries directly within your client-facing application? Sure, it might be easy to define and manage one or two boundaries, but when you’re working at scale, checking to see if something has exited or entered one of many boundaries could be a hassle.

In this tutorial, we’re going to explore the $near and $geoIntersects operators within MongoDB to define geofences and see if we’re within the fences. For the visual aspect of things, we’re going to make use of Mapbox for showing our geofences and our location.

To get an idea of what we’re going to build, take a look at the following animated image:

Geofencing with MongoDB and Mapbox

We’re going to implement functionality where a map is displayed and polygon shapes are rendered based on data from within MongoDB. When we move the marker around on the map to simulate actual changes in location, we’re going to determine whether or not we’ve entered or exited a geofence.

The Requirements

There are a few moving pieces for this particular tutorial, so it is important that the prerequisites are met prior to starting:

  • Must have a Mapbox account with an access token generated.
  • Must have a MongoDB Atlas cluster available.

Mapbox is a service, not affiliated with MongoDB. To render a map along with shapes and markers, an account is necessary. For this example, everything can be accomplished within the Mapbox free tier.

Because we’ll be using MongoDB Stitch in connection with Mapbox, we’ll need to be using MongoDB Atlas.

MongoDB Atlas can be used to deploy an M0 sized cluster of MongoDB for FREE.

The MongoDB Atlas cluster should have a location_services database with a geofences collection.

Understanding the GeoJSON Data to Represent Fenced Regions

To use the geospatial functionality that MongoDB offers, the data stored within MongoDB must be valid GeoJSON data. At the end of the day, GeoJSON is still JSON, which plays very nicely with MongoDB, but there is a specific schema that must be followed. To learn more about GeoJSON, visit the specification documentation.

For our example, we’re going to be working with Polygon and Point data. Take the following document model:

{
    "_id": ObjectId(),
    "name": string,
    "region": {
        "type": string,
        "coordinates": [
            [
                [double]
            ]
        ]
    }
}

In the above example, the region represents our GeoJSON data and everything above it such as name represents any additional data that we want to store for the particular document. A realistic example to the above model might look something like this:

{
    "_id": ObjectId("5ebdc11ab96302736c790694"),
    "name": "tracy",
    "region": {
        "type": "Polygon",
        "coordinates": [
            [
                [-121.56115581054638, 37.73644193427164],
                [-121.33868266601519, 37.59729761382843],
                [-121.31671000976553, 37.777700170855454],
                [-121.56115581054638, 37.73644193427164]
            ]
        ]
    }
}

We’re naming any of our possible fenced regions. This could be useful to a lot of organizations. For example, maybe you’re a business with several franchise locations. You could geofence the location and name it something like the address, store number, etc.

To get the performance we need from our geospatial data and to be able to use certain operators, we’re going to need to create an index on our collection. The index looks something like the following:

db.geofences.createIndex({ region: "2dsphere" })

The index can be created through Atlas, Compass, and with the CLI. The goal here is to make sure the region field is a 2dsphere index.

Configuring MongoDB Stitch for Client-Facing Application Interactions

Rather than creating a backend application to interact with the database, we’re going to make use of MongoDB Stitch. Essentially, the client-facing application will use the Stitch SDK to authenticate before interacting with the data.

Within the MongoDB Cloud, choose to create a new Stitch application if you don’t already have one that you wish to use. Make sure that the application is using the cluster that has your geofencing data.

Stitch Geofencing Application

Within the Stitch dashboard, choose the Rules tab and create a new set of permissions for the geofences collection. For this particular example, the Users can only read all data permission template is fine.

Next, we’ll want to choose an authentication mechanism. In the Users tab, choose Providers, and enable the anonymous authentication provider. In a more realistic production scenario, you’ll likely want to create geofences that have stricter users and rules design.

MongoDB Stitch Anonymous Authentication

Before moving onto actually creating an application, make note of your App ID within Stitch, as it will be necessary for connecting.

Interacting with the Geofences using Mapbox and MongoDB Geospatial Queries

With all the configuration out of the way, we can move into the fun part of creating an attractive client-facing application that queries the geospatial data in MongoDB and renders it on a map.

On your computer, create an index.html file with the following boilerplate code:

<!DOCTYPE html>
<head>
    <script src="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.js"></script>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.css" rel="stylesheet" />
    <script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4.6.0/stitch.js"></script>
</head>
<html>
    <body style="margin: 0">
        <div id="map" style="width: 100vw; height: 100vh"></div>
        <script>
            // Logic in here ...
        </script>
    </body>
</html>

In the above HTML, we’re importing the Mapbox and MongoDB Stitch SDKs, and we are defining an HTML container to hold our interactive map. Interacting with MongoDB and the map will be done in the <script> tag that follows.

Within the <script> tag, the first things we want to accomplish are around connecting to MongoDB Stitch and configuring map:

const client = stitch.Stitch.initializeDefaultAppClient("MONGODB_STITCH_APP_ID_HERE");
const db = client.getServiceClient(stitch.RemoteMongoClient.factory, "mongodb-atlas").db("location_services");
let currentLocationMarker;

client.auth.loginWithCredential(new stitch.AnonymousCredential());

mapboxgl.accessToken = "MAPBOX_ACCESS_TOKEN_HERE";
let map = new mapboxgl.Map({
    container: "map",
    style: "mapbox://styles/mapbox/streets-v11",
    center: [-121.4252, 37.7397],
    zoom: 9
});

The map should be centered somewhere around Tracy, CA, and MongoDB Stitch was configured to use the location_services database. Make sure to swap the tokens with your actual Mapbox and Stitch tokens.

The next step is to populate the map with markers and polygons when it loads:

map.on("load", async () => {
    currentLocationMarker = new mapboxgl.Marker().setLngLat([-121.29473735351542, 37.94575186984845]).addTo(map);
    map.addSource("UNIQUE_ID", {
        "type": "geojson",
        "data": {
            "type": "Feature",
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [-121.56115581054638, 37.73644193427164],
                        [-121.33868266601519, 37.59729761382843],
                        [-121.31671000976553, 37.777700170855454],
                        [-121.56115581054638, 37.73644193427164]
                    ]
                ]
            }
        }
    });
    map.addLayer({
        "id": "UNIQUE_ID",
        "type": "fill",
        "source": "UNIQUE_ID",
        "layout": {},
        "paint": {
            "fill-color": "#088",
            "fill-opacity": 0.8
        }
    });
});

In the above load event, we are creating a marker somewhere outside the center of the map and one single polygon shape. The thing is, we don’t want to hard-code our polygon shapes that represent geofence regions. Instead, add the GeoJSON data to MongoDB along with other possible fences.

We can change our load event to the following:

map.on("load", async () => {
    let fences = await db.collection("geofences").find({}).asArray();
    currentLocationMarker = new mapboxgl.Marker().setLngLat([-121.29473735351542, 37.94575186984845]).addTo(map);
    fences.forEach(fence => {
        map.addSource(fence.name, {
            "type": "geojson",
            "data": {
                "type": "Feature",
                "geometry": fence.region
            }
        });
        map.addLayer({
            "id": fence.name,
            "type": "fill",
            "source": fence.name,
            "layout": {},
            "paint": {
                "fill-color": "#088",
                "fill-opacity": 0.8
            }
        });
    });
});

In the above code, we query our collection for all documents and add them each as a layer on the map. We can do better though. In the above example, the geofences amount could be quite large and it doesn’t necessarily make sense to show all the fences that aren’t even remotely close to the current location. This would slow down the application for the client.

Instead, we can change the query to the following:

let fences = await db.collection("geofences").find({
    region: {
        $near: {
            $geometry: {
                type: "Point",
                coordinates: [-121.4252, 37.7397]
            },
            $maxDistance: 50000
        }
    }
}).asArray();

In the above code, we’re saying that we only want geofence results that are within 50,000 meters of our center point coordinate set. While our example doesn’t have many documents, this could be very beneficial in terms of performance.

Depending on the geofence data in MongoDB, you likely have some polygons drawn on the map as well as your marker. The next step is to move the marker around to simulate a change in location. We can do this with the click event for Mapbox:

map.on("click", async (e) => {
    currentLocationMarker.setLngLat([e.lngLat.lng, e.lngLat.lat]);
    let result = await db.collection("geofences").find({
        region: {
            $geoIntersects: {
                $geometry: {
                    type: "Point",
                    coordinates: [e.lngLat.lng, e.lngLat.lat]
                }
            }
        }
    }, { projection: { name: 1 }}).asArray();
    if(result.length > 0) {
        alert(`Within the ${result[0].name} fence!`);
    }
});

In the above code we make use of the $geoIntersects operator in our query. What this is doing is returning all documents where our point sits within the polygon shape. The marker is updated to wherever the map was clicked.

If there is an intersection, we just print out the first result to an alert. We do this because there could be overlapping geofences and for the scope of this example, we don’t need to worry about that.

Conclusion

You just saw how to leverage MongoDB and its ability to do geospatial queries to create geofences for a maps and location services type application. In the application we built, we stored GeoJSON data within MongoDB and queried for it using the $near and $geoIntersects operators. This allowed us to figure out what data we wanted based on a point location. We made use of Mapbox to give us a visual element as to whether or not our queries would return data.

Original article source at: https://developer.mongodb.com/

#mongodb #stitch #mapbox 

How to Location Geofencing with MongoDB, Stitch, and Mapbox
Monty  Boehm

Monty Boehm

1670492353

How to Searching for Nearby Points Of interest with MongoDB & Mapbox

When it comes to location data, MongoDB’s ability to work with GeoJSON through geospatial queries is often under-appreciated. Being able to query for intersecting or nearby coordinates while maintaining performance is functionality a lot of organizations are looking for.

Take the example of maintaining a list of business locations or even a fleet of vehicles. Knowing where these locations are, relative to a particular position isn’t an easy task when doing it manually.

In this tutorial we’re going to explore the $near operator within a MongoDB Realm application to find stored points of interest within a particular proximity to a position. These points of interest will be rendered on a map using the Mapbox service.

To get a better idea of what we’re going to accomplish, take the following animated image for example:

Places with MongoDB and Mapbox

We’re going to pre-load our MongoDB database with a few points of interest that are formatted using the GeoJSON specification. When clicking around on the map, we’re going to use the $near operator to find new points of interest that are within range of the marker.

The Requirements

There are numerous components that must be accounted for to be successful with this tutorial:

  • A MongoDB Atlas free tier cluster or better to store the data.
  • A MongoDB Realm application to access the data from a client-facing application.
  • A Mapbox free tier account or better to render the data on a map.

The assumption is that MongoDB Atlas has been properly configured and that MongoDB Realm is using the MongoDB Atlas cluster.

MongoDB Atlas can be used for FREE with a M0 sized cluster. Deploy MongoDB in minutes within the MongoDB Cloud.

In addition to Realm being pointed at the Atlas cluster, anonymous authentication for the Realm application should be enabled and an access rule should be defined for the collection. All users should be able to read all documents for this tutorial.

In this example, Mapbox is a third-party service for showing interactive map tiles. An account is necessary and an access token to be used for development should be obtained. You can learn how in the Mapbox documentation.

MongoDB Geospatial Queries and the GeoJSON Data Model

Before diving into geospatial queries and creating an interactive client-facing application, a moment should be taken to understand the data and indexes that must be created within MongoDB.

Take the following example document:

{
    "_id": "5ec6fec2318d26b626d53c61",
    "name": "WorkVine209",
    "location": {
        "type": "Point",
        "coordinates": [
            -121.4123,
            37.7621
        ]
    }
}

Let’s assume that documents that follow the above data model exist in a location_services database and a points_of_interest collection.

To be successful with our queries, we only need to store the location type and the coordinates. This location field makes up a GeoJSON feature, which follows a specific format. The name field, while useful isn’t an absolute requirement. Some other optional fields might include an address field, hours_of_operation, or similar.

Before being able to execute the geospatial queries that we want, we need to create a special index.

The following index should be created:

db.points_of_interest.createIndex({ location: "2dsphere" });

The above index can be created numerous ways, for example, you can create it using the MongoDB shell, Atlas, Compass, and a few other ways. Just note that the location field is being classified as a 2dsphere for the index.

With the index created, we can execute a query like the following:

db.points_of_interest.find({
    "location": {
        "$near": {
            "$geometry": {
                "type": "Point",
                "coordinates": [-121.4252, 37.7397]
            },
            "$maxDistance": 2500
        }
    }
});

Notice in the above example, we’re looking for documents that have a location field within 2,500 meters of the point provided in the filter.

With an idea of how the data looks and how the data can be accessed, let’s work towards creating a functional application.

Interacting with Places using MongoDB Realm and Mapbox

Like previously mentioned, you should already have a Mapbox account and MongoDB Realm should already be configured.

On your computer, create an index.html file with the following boilerplate code:

<!DOCTYPE html>
<head>
    <script src="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.js"></script>
    <link href="https://api.mapbox.com/mapbox-gl-js/v1.10.0/mapbox-gl.css" rel="stylesheet" />
    <script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4.6.0/stitch.js"></script>
</head>
<html>
    <body style="margin: 0">
        <div id="map" style="width: 100vw; height: 100vh"></div>
        <script>
            // Logic here ...
        </script>
    </body>
</html>

In the above code, we’re including both the Mapbox library as well as the MongoDB Realm SDK. We’re creating a map placeholder component which will show our map, and it is lightly styled with CSS.

You can run this file locally, serve it, or host it on MongoDB Realm.

Within the <script> tags, we can initialize a few things with the following lines of code:

const client = stitch.Stitch.initializeDefaultAppClient("MONGODB_REALM_APP_ID_HERE);
const db = client.getServiceClient(stitch.RemoteMongoClient.factory, "mongodb-atlas").db("location_services");
mapboxgl.accessToken = "MAPBOX_ACCESS_TOKEN_HERE";

var currentLocationMarker = new mapboxgl.Marker({ color: "red" }).setLngLat([-121.4252, 37.7397]);
var placeMarkers = [];

let map = new mapboxgl.Map({
    container: "map",
    style: "mapbox://styles/mapbox/streets-v11",
    center: [-121.4252, 37.7397],
    zoom: 13
});

map.doubleClickZoom.disable();

In the above code we’re telling both MongoDB Realm and Mapbox which tokens to use. We’re also defining some basic configuration information for our map and which database to use for Realm.

The currentLocationMarker will represent a mock of our location and the placesMarkers will represent any nearby points of interest.

It should be noted, that we haven’t yet connected to MongoDB in our code. We want to wait until the map is ready, so we have to make use of event listeners.

Take the following code for example:

map.on("load", async () => {
    await client.auth.loginWithCredential(new stitch.AnonymousCredential());
    currentLocationMarker.addTo(map);
    // Find points of interest near marker
});

When the map is considered ready, we do anonymous authentication to MongoDB Realm and we add our current location to the map as a marker. When the map is loaded, we’re also going to want to find any points of interest near our marker. This is where our geospatial query comes into play.

Outside of the event listener, create the following function:

const getPointsOfInterest = async (position) => {
    let places = await db.collection("points_of_interest").find({
        "location": {
            "$near": {
                "$geometry": {
                    "type": "Point",
                    "coordinates": position
                },
                "$maxDistance": 2500
            }
        }
    }).toArray();
    return places.map(place => (new mapboxgl.Marker().setLngLat(place.location.coordinates)).setPopup(new mapboxgl.Popup({ offset: 25 }).setText(place.name)));
};

Most of the function should look familiar. We’re accepting a position array and using it within the $near operation of the query. The results of the query are loaded into an array and the results are then transformed into map markers that include a popup. The popup will show the name information for the point of interest.

With the above function in place, we can go back into the load event listener and change it to the following:

map.on("load", async () => {
    await client.auth.loginWithCredential(new stitch.AnonymousCredential());
    currentLocationMarker.addTo(map);
    placeMarkers = await getPointsOfInterest([-121.4252, 37.7397]);
    placeMarkers.forEach(marker => marker.addTo(map));
});

Each marker returned from the getPointsOfInterest function will be added to the map.

This is great, but we can take it a step further by interacting with the map and continuously doing queries based on our new location. Let’s add another event listener:

map.on("dblclick", async (e) => {
    currentLocationMarker.setLngLat([e.lngLat.lng, e.lngLat.lat]);
    placeMarkers.forEach(marker => marker.remove());
    placeMarkers = await getPointsOfInterest([e.lngLat.lng, e.lngLat.lat]);
    placeMarkers.forEach(marker => marker.addTo(map));
});

When the map is double clicked, the marker location is updated, all previous markers are removed, and new points of interest are queried for.

Want to search for specific points of interest that might be nearby? You can take your getPointsOfInterest function a bit further by having a find operation like the following:

let places = await db.collection("points_of_interest").find({
    "location": {
        "$near": {
            "$geometry": {
                "type": "Point",
                "coordinates": position
            },
            "$maxDistance": 2500
        }
    },
    "name": "Target"
}).toArray();

Notice that in the above code we’re saying that the location has to be near our point and the name has to be Target. The odds of having multiple Target stores within our range is slim, but imagine if Starbucks was used, or if your example included different kinds of data.

Conclusion

You just saw how to use the $near operator to potentially find points of interest with geospatial queries in MongoDB. To make this example more exciting, we rendered our results on a map using Mapbox, and linked the client-facing Mapbox application to our database with MongoDB Realm.

If you’d like to see more Mapbox with MongoDB examples, check out my tutorial titled, Location Geofencing with MongoDB, Realm, and Mapbox.

Original article source at: https://www.mongodb.com/

#mongodb #mapbox #javascript 

How to Searching for Nearby Points Of interest with MongoDB & Mapbox
Nat  Grady

Nat Grady

1666344300

Mapboxer: An R Interface to Mapbox GL JS

Mapboxer: An R Interface to Mapbox GL JS

mapboxer makes Mapbox GL JS, an open source JavaScript library that uses WebGL to render interactive maps, available within R via the htmlwidgets package.

persons-in-manhatten

Note

mapboxer provides bindings to v1.x.x of Mapbox GL JS, which is under the 3-Clause BSD license. See also breaking changes in Mapbox GL JS v2.0.0.

Installation

Install the release version from CRAN with:

install.packages("mapboxer")

Install the development version from GitHub with:

# install.packages("remotes")
remotes::install_github("crazycapivara/mapboxer")

Usage

library(mapboxer)

map <- motor_vehicle_collisions_nyc %>%
  dplyr::mutate(
    color = ifelse(injured == 0, "yellow", "red")
  ) %>%
  as_mapbox_source() %>%
  mapboxer(
    center = c(-73.9165, 40.7114),
    zoom = 10
  ) %>%
  add_navigation_control() %>%
  add_circle_layer(
    circle_color = c("get", "color"),
    circle_blur = 1,
    circle_stroke_color = "red",
    circle_stroke_width = 1,
    popup = "<p>{{date}} {{time}}</p><p>Number of persons injured: {{injured}}</p>"
  )

if (interactive()) map

By default mapboxer uses Carto vector styles as basemaps. It is also possible to use raster tiles or a background color.

If you want to use styles from Mapbox it is recommended that you store your API token in an environment vatiable called MAPBOX_API_TOKEN.

Documentation

Development

All JavaScript code of mapboxer is located in javascript/src.

Install dependencies and build the library with:

npm install
npm run build

The module is written to inst/htmlwidgets.

Spin up the dev server with:

npm run start

Download Details:

Author: crazycapivara
Source Code: https://github.com/crazycapivara/mapboxer 
License: Unknown, MIT licenses found

#r #webgl #mapbox 

Mapboxer: An R Interface to Mapbox GL JS

A Mapbox GL Flutter Package for Creating Custom Maps

Flutter Mapbox GL

Please note that this project is community driven and is not an official Mapbox product.

We welcome feedback and contributions.

Table of contents

Introduction

This Flutter plugin allows to show embedded interactive and customizable vector maps inside a Flutter widget. For the Android and iOS integration, we use mapbox-gl-native. For web, we rely on mapbox-gl-js. This project only supports a subset of the API exposed by these libraries.

screenshot.png

Setting up

This package is available on pub.dev.

Get it by running the following command:

flutter pub add mapbox_gl

Mobile

Secret Mapbox access token

A secret access token with the Downloads: Read scope is required for the underlying Mapbox SDKs to be downloaded. Information on setting it up is available in the Mapbox documentation: Android, iOS.

If the properly configured token is not present, the build process fails with one the following errors (for Android/iOS respectively):

* What went wrong:
A problem occurred evaluating project ':mapbox_gl'.
> SDK Registry token is null. See README.md for more information.
[!] Error installing Mapbox-iOS-SDK
curl: (22) The requested URL returned error: 401 Unauthorized

Web

Include the JavaScript and CSS files in the <head> of your index.html file:

<script src='https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.css' rel='stylesheet' />

<style>
   .mapboxgl-map {
      position: relative;
      width: 100%;
      height: 100%;
    }
</style>

Note: Look for latest version in Mapbox GL JS documentation.

All platforms

Public Mapbox access token

A public access token must be provided to a MapboxMap widget for retrieving styles and resources. While you can hardcode it directly into source files, it's good practise to retrieve access tokens from some external source (e.g. a config file or an environment variable). The example app uses the following technique:

The access token is passed via the command line arguments when either building

flutter build <platform> --dart-define ACCESS_TOKEN=YOUR_TOKEN_HERE

or running the application

flutter run --dart-define ACCESS_TOKEN=YOUR_TOKEN_HERE

Then it's retrieved in Dart:

MapboxMap(
  ...
  accessToken: const String.fromEnvironment("ACCESS_TOKEN"),
  ...
)

Supported API

FeatureAndroidiOSWeb
Style:white_check_mark::white_check_mark::white_check_mark:
Camera:white_check_mark::white_check_mark::white_check_mark:
Gesture:white_check_mark::white_check_mark::white_check_mark:
User Location:white_check_mark::white_check_mark::white_check_mark:
Style DSL:x::x::x:
Raster Layer:white_check_mark::white_check_mark::white_check_mark:
Symbol Layer:white_check_mark::white_check_mark::white_check_mark:
Circle Layer:white_check_mark::white_check_mark::white_check_mark:
Line Layer:white_check_mark::white_check_mark::white_check_mark:
Fill Layer:white_check_mark::white_check_mark::white_check_mark:
Fill Extrusion Layer:white_check_mark::white_check_mark::white_check_mark:
Hillshade Layer:white_check_mark::white_check_mark::white_check_mark:
Heatmap Layer:white_check_mark::white_check_mark::white_check_mark:
Vector Source:white_check_mark::white_check_mark::white_check_mark:
Raster Source:white_check_mark::white_check_mark::white_check_mark:
GeoJson Source:white_check_mark::white_check_mark::white_check_mark:
Image Source:white_check_mark::white_check_mark::white_check_mark:
Expressions:white_check_mark::white_check_mark::white_check_mark:
Symbol Annotation:white_check_mark::white_check_mark::white_check_mark:
Circle Annotation:white_check_mark::white_check_mark::white_check_mark:
Line Annotation:white_check_mark::white_check_mark::white_check_mark:
Fill Annotation:white_check_mark::white_check_mark::white_check_mark:

Map Styles

Map styles can be supplied by setting the styleString in the MapOptions. The following formats are supported:

  1. Passing the URL of the map style. This can be one of the built-in map styles, also see MapboxStyles or a custom map style served remotely using a URL that start with 'http(s)://' or 'mapbox://'
  2. Passing the style as a local asset. Create a JSON file in the assets and add a reference in pubspec.yml. Set the style string to the relative path for this asset in order to load it into the map.
  3. Passing the style as a local file. create an JSON file in app directory (e.g. ApplicationDocumentsDirectory). Set the style string to the absolute path of this JSON file.
  4. Passing the raw JSON of the map style. This is only supported on Android.

Offline Sideloading

Support for offline maps is available by side loading the required map tiles and including them in your assets folder.

Create your tiles package by following the guide available here.

Place the tiles.db file generated in step one in your assets directory and add a reference to it in your pubspec.yml file.

   assets:
     - assets/cache.db
  • Call installOfflineMapTiles when your application starts to copy your tiles into the location where Mapbox can access them. NOTE: This method should be called before the Map widget is loaded to prevent collisions when copying the files into place.
    try {
      await installOfflineMapTiles(join("assets", "cache.db"));
    } catch (err) {
      print(err);
    }

Downloading Offline Regions

An offline region is a defined region of a map that is available for use in conditions with limited or no network connection. Tiles for selected region, style and precision are downloaded from Mapbox using proper SDK methods and stored in application's cache.

Beware of selecting big regions, as size might be significant. Here is an online estimator https://docs.mapbox.com/playground/offline-estimator/.

Call downloadOfflineRegionStream with predefined OfflineRegion and optionally track progress in the callback function.

    final Function(DownloadRegionStatus event) onEvent = (DownloadRegionStatus status) {
      if (status.runtimeType == Success) {
        // ...
      } else if (status.runtimeType == InProgress) {
        int progress = (status as InProgress).progress.round();
        // ...
      } else if (status.runtimeType == Error) {
        // ...
      }
    };

    final OfflineRegion offlineRegion = OfflineRegion(
      bounds: LatLngBounds(
        northeast: LatLng(52.5050648, 13.3915634),
        southwest: LatLng(52.4943073, 13.4055383),
      ),
      id: 1,
      minZoom: 6,
      maxZoom: 18,
      mapStyleUrl: 'mapbox://styles/mapbox/streets-v11',
    );

    downloadOfflineRegionStream(offlineRegion, onEvent);

Create a static map snapshot

The snapshotManager generates static raster images of the map. Each snapshot image depicts a portion of a map defined by an SnapshotOptions object you provide.

  • Call takeSnapshot with predefined SnapshotOptions
    final renderBox = mapKey.currentContext?.findRenderObject() as RenderBox;

    final snapshotOptions = SnapshotOptions(
      width: renderBox.size.width,
      height: renderBox.size.height,
      writeToDisk: true,
      withLogo: false,
    );
    
    final uri = await mapController?.takeSnapshot(snapshotOptions);

Location features

Android

Add the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in the application manifest android/app/src/main/AndroidManifest.xml to enable location features in an Android application:

<manifest ...
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Starting from Android API level 23 you also need to request it at runtime. This plugin does not handle this for you. The example app uses the flutter 'location' plugin for this.

iOS

To enable location features in an iOS application:

If you access your users' location, you should also add the following key to ios/Runner/Info.plist to explain why you need access to their location data:

xml ...
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>[Your explanation here]</string>

Recommended explanation about "Shows your location on the map and helps improve the map".

Flutter 3.x.x issues and experimental workarounds

Since Flutter 3.x.x was introduced, it exposed some race conditions resulting in occasional crashes upon map disposal. The parameter useDelayedDisposal was introduced as a workaround for this issue until Flutter and/or Mapbox fix this issue properly. Use with caution - this is not yet production ready since several users still report crashes after using this workaround.

Running the example code

See the documentation about this topic

Contributing

We welcome contributions to this repository! If you're interested in helping build this Mapbox-Flutter integration, please read the contribution guide to learn how to get started.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add mapbox_gl_platform_interface

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  mapbox_gl_platform_interface: ^0.16.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart'; 

Download Details:

Author: flutter-mapbox-gl

Source Code: https://github.com/flutter-mapbox-gl/maps

#map #flutter #mapbox 

A Mapbox GL Flutter Package for Creating Custom Maps
Nat  Grady

Nat Grady

1665598800

Rdeck: Deck.gl Widget for R

 rdeck 

deck.gl widget for R.
 

documentation

Installation

# install latest release
remotes::install_github("qfes/rdeck@*release")
# or install development version
remotes::install_github("qfes/rdeck")

Mapbox access token

A Mapbox account and mapbox access token is required for Mapbox basemaps, with or without the Mapbox data service. See mapbox_access_token for usage.

Similar work

{rdeck} draws much inspiration from kepler.gl and {mapdeck}. {rdeck}'s design choices make it convenient for use in static reports, and certain Shiny usecases that are highly performant.

Some notable differences to {mapdeck}:

  • {rmarkdown} HTML reports made with {rdeck} are typically an order of magnitude smaller in file size than {mapdeck}. Thanks to:
    • column-major data storage
    • client-side visual attributes scaling
    • client-side tooltip formatting
    • automatic filtering of data that is not used in the map
  • Tidy evaluation is supported for column specifications.
  • Extensive validation of layer properties in R is preferred, rather than throwing errors in the browser.
  • {ggplot2} style scale_ functions that perform common layer data transformations and automatically generate legends with appropriate untransformed tick marks.
    • e.g. scale_color_power, scale_color_log etc.
  • Automatic creation of formatted tooltips
  • Choice of light or dark themes for tooltips and legends.
  • Auto-generated interface from JS source
    • every deck.gl layer is supported to some degree
    • every layer property is a snake_case version of the camelCase deck.gl counterpart.
  • Users can orchestrate browser-side map layer updates with Shiny, allowing for extremely performant reactivity.
    • Traditional Shiny interactivity using whole datasets is also possible, and is slightly slower than {mapdeck} at present.

Download Details:

Author: qfes
Source Code: https://github.com/qfes/rdeck 
License: MIT license

#r #mapbox #widget 

Rdeck: Deck.gl Widget for R
Nat  Grady

Nat Grady

1665431040

Mapdeck: R interface to Deck.gl and Mapbox

mapdeck

What is mapdeck?

An R library which lets you plot large data sets (as much as your GPU & browser can handle), on interactive maps using Mapbox GL and Deck.gl

polygon_transitions.gif

What is mapbox?

Mapbox is the location data platform for mobile and web applications. We provide building blocks to add location features like maps, search, and navigation into any experience you create.

What is deck.gl?

deck.gl is a WebGL-powered framework for visual exploratory data analysis of large datasets.

How do I use it?

First you need to install it, either from CRAN

install.packages("mapdeck")

Or from github (to get the latest development version)

remotes::install_github("SymbolixAU/mapdeck")

If the github version fails to install, you’ll probably need to update dependencies first

remotes::install_github("dcooley/geometries")
remotes::install_github("dcooley/sfheaders")
remotes::install_github("SymbolixAU/spatialwidget")

Then everything you need to know to get you started is on the home page

Quick Start

Mapdeck uses Mapbox maps, and to use Mapbox you need an access token.

Once you’ve generate a token you can use their maps.

Call mapdeck(token = 'your_token') to generate a basic map. Then start adding layers by using one of the various add_*() functions.

url <- 'https://raw.githubusercontent.com/plotly/datasets/master/2011_february_aa_flight_paths.csv'
flights <- read.csv(url)
flights$info <- paste0("<b>",flights$airport1, " - ", flights$airport2, "</b>")

mapdeck(token = key, style = mapdeck_style('dark')) %>%
  add_arc(
    data = flights
    , origin = c("start_lon", "start_lat")
    , destination = c("end_lon", "end_lat")
    , stroke_from = "airport1"
    , stroke_to = "airport2"
    , tooltip = "info"
    , layer_id = 'arclayer'
  )

Arcs

See the Layers page for more examples

Getting help

For general help and advice the best place to ask is on StackOverflow (using the mapdeck tag).

If you’ve found a bug, or want a new feature added then use the issue tracker on github.

I don’t respond to emails asking for help because this is an open source package, and any advice should be kept open so everyone can benefit. (unless you want to pay me!)

Download Details:

Author: SymbolixAU
Source Code: https://github.com/SymbolixAU/mapdeck 

#r #mapbox #maps 

Mapdeck: R interface to Deck.gl and Mapbox

A Mapbox GL Flutter Package for Creating Custom Maps

Flutter Mapbox GL

Please note that this project is community driven and is not an official Mapbox product.

We welcome feedback and contributions.

Table of contents

Introduction

This Flutter plugin allows to show embedded interactive and customizable vector maps inside a Flutter widget. For the Android and iOS integration, we use mapbox-gl-native. For web, we rely on mapbox-gl-js. This project only supports a subset of the API exposed by these libraries.

Setting up

This package is available on pub.dev.

Get it by running the following command:

flutter pub add mapbox_gl

Mobile

Secret Mapbox access token

A secret access token with the Downloads: Read scope is required for the underlying Mapbox SDKs to be downloaded. Information on setting it up is available in the Mapbox documentation: Android, iOS.

If the properly configured token is not present, the build process fails with one the following errors (for Android/iOS respectively):

* What went wrong:
A problem occurred evaluating project ':mapbox_gl'.
> SDK Registry token is null. See README.md for more information.
[!] Error installing Mapbox-iOS-SDK
curl: (22) The requested URL returned error: 401 Unauthorized

Web

Include the JavaScript and CSS files in the <head> of your index.html file:

<script src='https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.css' rel='stylesheet' />

<style>
   .mapboxgl-map {
      position: relative;
      width: 100%;
      height: 100%;
    }
</style>

Note: Look for latest version in Mapbox GL JS documentation.

All platforms

Public Mapbox access token

A public access token must be provided to a MapboxMap widget for retrieving styles and resources. While you can hardcode it directly into source files, it's good practise to retrieve access tokens from some external source (e.g. a config file or an environment variable). The example app uses the following technique:

The access token is passed via the command line arguments when either building

flutter build <platform> --dart-define ACCESS_TOKEN=YOUR_TOKEN_HERE

or running the application

flutter run --dart-define ACCESS_TOKEN=YOUR_TOKEN_HERE

Then it's retrieved in Dart:

MapboxMap(
  ...
  accessToken: const String.fromEnvironment("ACCESS_TOKEN"),
  ...
)

Supported API

FeatureAndroidiOSWeb
Style:white_check_mark::white_check_mark::white_check_mark:
Camera:white_check_mark::white_check_mark::white_check_mark:
Gesture:white_check_mark::white_check_mark::white_check_mark:
User Location:white_check_mark::white_check_mark::white_check_mark:
Style DSL:x::x::x:
Raster Layer:white_check_mark::white_check_mark::white_check_mark:
Symbol Layer:white_check_mark::white_check_mark::white_check_mark:
Circle Layer:white_check_mark::white_check_mark::white_check_mark:
Line Layer:white_check_mark::white_check_mark::white_check_mark:
Fill Layer:white_check_mark::white_check_mark::white_check_mark:
Hillshade Layer:white_check_mark::white_check_mark::white_check_mark:
Heatmap Layer:x::x::x:
Vector Source:white_check_mark::white_check_mark::white_check_mark:
Raster Source:white_check_mark::white_check_mark::white_check_mark:
GeoJson Source:white_check_mark::white_check_mark::white_check_mark:
Image Source:white_check_mark::white_check_mark::white_check_mark:
Expressions:white_check_mark::white_check_mark::white_check_mark:
Symbol Annotation:white_check_mark::white_check_mark::white_check_mark:
Circle Annotation:white_check_mark::white_check_mark::white_check_mark:
Line Annotation:white_check_mark::white_check_mark::white_check_mark:
Fill Annotation:white_check_mark::white_check_mark::white_check_mark:

Map Styles

Map styles can be supplied by setting the styleString in the MapOptions. The following formats are supported:

  1. Passing the URL of the map style. This can be one of the built-in map styles, also see MapboxStyles or a custom map style served remotely using a URL that start with 'http(s)://' or 'mapbox://'
  2. Passing the style as a local asset. Create a JSON file in the assets and add a reference in pubspec.yml. Set the style string to the relative path for this asset in order to load it into the map.
  3. Passing the style as a local file. create an JSON file in app directory (e.g. ApplicationDocumentsDirectory). Set the style string to the absolute path of this JSON file.
  4. Passing the raw JSON of the map style. This is only supported on Android.

Offline Sideloading

Support for offline maps is available by side loading the required map tiles and including them in your assets folder.

Create your tiles package by following the guide available here.

Place the tiles.db file generated in step one in your assets directory and add a reference to it in your pubspec.yml file.

   assets:
     - assets/cache.db
  • Call installOfflineMapTiles when your application starts to copy your tiles into the location where Mapbox can access them. NOTE: This method should be called before the Map widget is loaded to prevent collisions when copying the files into place.
    try {
      await installOfflineMapTiles(join("assets", "cache.db"));
    } catch (err) {
      print(err);
    }

Downloading Offline Regions

An offline region is a defined region of a map that is available for use in conditions with limited or no network connection. Tiles for selected region, style and precision are downloaded from Mapbox using proper SDK methods and stored in application's cache.

Beware of selecting big regions, as size might be significant. Here is an online estimator https://docs.mapbox.com/playground/offline-estimator/.

Call downloadOfflineRegionStream with predefined OfflineRegion and optionally track progress in the callback function.

    final Function(DownloadRegionStatus event) onEvent = (DownloadRegionStatus status) {
      if (status.runtimeType == Success) {
        // ...
      } else if (status.runtimeType == InProgress) {
        int progress = (status as InProgress).progress.round();
        // ...
      } else if (status.runtimeType == Error) {
        // ...
      }
    };

    final OfflineRegion offlineRegion = OfflineRegion(
      bounds: LatLngBounds(
        northeast: LatLng(52.5050648, 13.3915634),
        southwest: LatLng(52.4943073, 13.4055383),
      ),
      id: 1,
      minZoom: 6,
      maxZoom: 18,
      mapStyleUrl: 'mapbox://styles/mapbox/streets-v11',
    );

    downloadOfflineRegionStream(offlineRegion, onEvent);

Create a static map snapshot

The snapshotManager generates static raster images of the map. Each snapshot image depicts a portion of a map defined by an SnapshotOptions object you provide.

  • Call takeSnapshot with predefined SnapshotOptions
    final renderBox = mapKey.currentContext?.findRenderObject() as RenderBox;

    final snapshotOptions = SnapshotOptions(
      width: renderBox.size.width,
      height: renderBox.size.height,
      writeToDisk: true,
      withLogo: false,
    );
    
    final uri = await mapController?.takeSnapshot(snapshotOptions);

Location features

Android

Add the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in the application manifest android/app/src/main/AndroidManifest.xml to enable location features in an Android application:

<manifest ...
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Starting from Android API level 23 you also need to request it at runtime. This plugin does not handle this for you. The example app uses the flutter 'location' plugin for this.

iOS

To enable location features in an iOS application:

If you access your users' location, you should also add the following key to ios/Runner/Info.plist to explain why you need access to their location data:

xml ...
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>[Your explanation here]</string>

Recommended explanation about "Shows your location on the map and helps improve the map".

Running the example code

See the documentation about this topic

Contributing

We welcome contributions to this repository! If you're interested in helping build this Mapbox-Flutter integration, please read the contribution guide to learn how to get started.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add vtmap_gl_platform_interface

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  vtmap_gl_platform_interface: ^0.0.8

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:vtmap_gl_platform_interface/vtmap_gl_platform_interface.dart'; 

Download Details:

Author: flutter-mapbox-gl

Source Code: https://github.com/flutter-mapbox-gl/maps

#flutter #map #mapbox 

A Mapbox GL Flutter Package for Creating Custom Maps
Nat  Grady

Nat Grady

1658886660

Geojsonapp: Preview Geojson Files Locally W/ Electron and Mapbox GL

Geojsonapp

Preview geojson locally using Electron and Mapbox GL

geojsonapp

Install:

npm install -g geojsonapp

Run:

geojsonapp

Open file:

geojsonapp filename.geojson

cat filename.geojson | geojsonapp

Author: Mick
Source Code: https://github.com/mick/geojsonapp 
License: 

#electron #mapbox 

Geojsonapp: Preview Geojson Files Locally W/ Electron and Mapbox GL
Nat  Grady

Nat Grady

1657254780

Mapbox Studio is The Modern Alternative to Mapbox Studio Classic

Mapbox Studio is the modern alternative to Mapbox Studio Classic: if you're starting out and creating a map today, we recommend starting with Mapbox Studio rather than Mapbox Studio Classic.

Desktop application for vector tile driven map design. 

Install from source

Install node v0.10.x. Then

git clone https://github.com/mapbox/mapbox-studio-classic.git
cd mapbox-studio-classic
npm install
npm start

Depends

Mapbox Studio Classic ships with pre-built binaries for common platforms:

  • 32 and 64 bit Windows
  • 64 bit OS X
  • 64 bit Linux

The minimum platforms versions are:

  • Windows >= 7
  • OS X >= 10.8
  • Ubuntu >= 14.04 (Trusty)
  • RHEL/Centos >= 7

Ubuntu 12.04 (Precise) can be supported by upgrading libstdc++:

sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update -q
sudo apt-get install -y libstdc++6

If packages like node-mapnik fail to install then you are likely running a platform for which no binaries are available. In this case you will need to build these packages from source (Feel free to create a github issue to ask for help).

You can do this like:

npm install --build-from-source

Getting started

The docs offer both a step-by-step guide to creating your first projects in Mapbox Studio Classic and detailed information about styling and creating vector sources.

View documentation


Build status of modules:

  • mapnik - Build Status
  • node-mapnik - Build Status
  • carto - Build Status
  • tilelive - Build Status
  • tilelive-vector - Build Status
  • tilelive-bridge - Build Status

Author: Mapbox
Source Code: https://github.com/mapbox/mapbox-studio-classic 
License: BSD-3-Clause license

#electron #mapbox #javascript 

Mapbox Studio is The Modern Alternative to Mapbox Studio Classic

Mapbox GL: interactive, Customizable Vector Maps By Mapbox

Flutter Mapbox GL Native

This Flutter plugin for mapbox-gl-native enables embedded interactive and customizable vector maps inside of a Flutter widget. This project plugin is in early development stage. Only Android is supported for now.

screenshot.png

Getting Started

Android

Following examples use Mapbox vector tiles, which require a Mapbox account and a Mapbox access token. Obtain a free access token on your Mapbox account page. After you get the key, place it in project's Android directory:

  • Create a local.properties file with the following path: $project_dir/android/local.properties
  • Add mapbox.accessToken="YOUR MAPBOX ACCESS TOKEN" token to the local.properties file.

Demo app

  • Install Flutter and validate its installation with flutter doctor
  • Clone this repository with git clone git@github.com:mapbox/flutter-mapbox-gl.git
  • Run the app with cd flutter_mapbox/example && flutter run

New project

  • Create new Flutter project in your IDE or via terminal
  • Add mapbox_gl: ^0.0.1 dependency to pubspec.yaml file and get the package
  • Add Mapbox read token value in the application manifest android/app/src/main/AndroidManifest.xml:
<manifest ...
  <application ...
    <meta-data android:name="com.mapbox.token" android:value="YOUR_TOKEN_HERE" />
  • Import Mapbox widgets and add them to your widget tree
import 'package:mapbox_gl/mapbox_gl.dart';

Documentation

This README file currently houses all of the documentation for this Flutter project. Please visit mapbox.com/android-docs if you'd like more information about the Mapbox Maps SDK for Android and mapbox.com/ios-sdk for more information about the Mapbox Maps SDK for iOS.

Getting Help

  • Need help with your code?: Look for previous questions on the #mapbox tag — or ask a new question.
  • Have a bug to report? Open an issue. If possible, include a full log and information which shows the issue.
  • Have a feature request? Open an issue. Tell us what the feature should do and why you want the feature.

Sample code

This repository's example library is currently the best place for you to find reference code for this project.

Contributing

We welcome contributions to this repository!

If you're interested in helping build this Mapbox/Flutter integration, please read the contribution guide to learn how to get started.

Please note that this project has moved. Please head to https://github.com/tobrun/flutter-mapbox-gl for updates.

Author: Mapbox
Source Code: https://github.com/mapbox/flutter-mapbox-gl 
License: View license

#flutter #dart 

Mapbox GL: interactive, Customizable Vector Maps By Mapbox

A New Flutter Plugin for Mapbox

Mapbox Flutter

This project is inspired by Mapbox_gl

This project also integrates the Null_Safety

We welcome feedback and contributions.

mapbox.PNG

Running the example app

  • Install Flutter and validate its installation with flutter doctor
  • Clone the repository with git clone git@github.com:BorisGautier/mapbox_flutter.git
  • Add a public Mapbox access token to the example app (see next section)
  • Add a secret Mapbox access token for downloading the SDK
  • Connect a mobile device or start an emulator, simulator or chrome
  • Locate the id of a the device with flutter devices
  • Run the app with cd mapbox_flutter/example && flutter packages get && flutter run -d {device_id}

Adding a Mapbox Access Token

This project uses Mapbox vector tiles, which requires a Mapbox account and a Mapbox access token. Obtain a free access token on your Mapbox account page.

Even if you do not use Mapbox vector tiles but vector tiles from a different source (like self-hosted tiles) with this plugin, you will need to specify any non-empty string as Access Token as explained below!

The recommended way to provide your access token is through the accessToken parameter of the MapboxFlutterMap constructor Note that you should always use the same token throughout your application.

Adding a Mapbox Access Token

This project uses Mapbox vector tiles, which requires a Mapbox account and a Mapbox access token. Obtain a free access token on your Mapbox account page.

Even if you do not use Mapbox vector tiles but vector tiles from a different source (like self-hosted tiles) with this plugin, you will need to specify any non-empty string as Access Token as explained below!

Providing your access token in Flutter (recommended)

The recommended way to provide your access token is through the MapboxFlutterMap constructor's accessToken parameter. Note that you should always use the same token throughout your entire app.


Setting your access token through platform-specific files (old method)

For earlier versions you need to set your access token through platform-specific files as described below. This will also continue to work as a fallback on v0.8. You should not set the access token through both the constructor parameter and platform-specific files!

Android

Add Mapbox access token configuration in the application manifest example/android/app/src/main/AndroidManifest.xml:

<manifest ...
  <application ...
    <meta-data android:name="com.mapbox.token" android:value="YOUR_TOKEN_HERE" />

iOS

Add Mapbox access token configuration to the application Info.plist example/ios/Runner/Info.plist:

<key>io.flutter.embedded_views_preview</key>
<true/>
<key>MGLMapboxAccessToken</key>
<string>YOUR_TOKEN_HERE</string>

Web

Add Mapbox access token configuration to index.html example/web/index.html:

<body>
  ...
  <script>
    mapboxgl.accessToken = 'YOUR_TOKEN_HERE';
  </script>
</body>

SDK Download token

You must also [configure a secret access token having the Download: read scope][https://docs.mapbox.com/ios/maps/guides/install/]. If this configuration is not present, an error like the following appears during the iOS build.

[!] Error installing Mapbox-iOS-SDK
curl: (22) The requested URL returned error: 401 Unauthorized

Avoid Android UnsatisfiedLinkError

Update buildTypes in android\app\build.gradle

buildTypes {
    release {
        // other configs
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a','x86_64', 'x86'
        }
    }
}

Using the SDK in your project

This project is available on pub.dev, follow the instructions to integrate a package into your flutter application. For platform specific integration, use the flutter application under the example folder as reference.

Supported API

FeatureAndroidiOSWeb
Style
Camera
Gesture
User Location
Symbol
Circle
Line
Fill

Map Styles

Map styles can be supplied by setting the styleString in the MapOptions. The following formats are supported:

  1. Passing the URL of the map style. This can be one of the built-in map styles, also see MapboxStyles or a custom map style served remotely using a URL that start with 'http(s)://' or 'mapbox://'
  2. Passing the style as a local asset. Create a JSON file in the assets and add a reference in pubspec.yml. Set the style string to the relative path for this asset in order to load it into the map.
  3. Passing the style as a local file. create an JSON file in app directory (e.g. ApplicationDocumentsDirectory). Set the style string to the absolute path of this JSON file.
  4. Passing the raw JSON of the map style. This is only supported on Android.

Offline Sideloading

Support for offline maps is available by "side loading" the required map tiles and including them in your assets folder.

Create your tiles package by following the guide available here.

Place the tiles.db file generated in step one in your assets directory and add a reference to it in your pubspec.yml file.

   assets:
     - assets/cache.db
  • Call installOfflineMapTiles when your application starts to copy your tiles into the location where Mapbox can access them. NOTE: This method should be called before the Map widget is loaded to prevent collisions when copying the files into place.
    try {
      await installOfflineMapTiles(join("assets", "cache.db"));
    } catch (err) {
      print(err);
    }

Downloading Offline Regions

An offline region is a defined region of a map that is available for use in conditions with limited or no network connection. Tiles for selected region, style and precision are downloaded from Mapbox using proper SDK methods and stored in application's cache.

Beware of selecting big regions, as size might be significant. Here is an online estimator https://docs.mapbox.com/playground/offline-estimator/.

Call downloadOfflineRegionStream with predefined OfflineRegion and optionally track progress in the callback function.

    final Function(DownloadRegionStatus event) onEvent = (DownloadRegionStatus status) {
      if (status.runtimeType == Success) {
        // ...
      } else if (status.runtimeType == InProgress) {
        int progress = (status as InProgress).progress.round();
        // ...
      } else if (status.runtimeType == Error) {
        // ...
      }
    };

    final OfflineRegion offlineRegion = OfflineRegion(
      bounds: LatLngBounds(
        northeast: LatLng(52.5050648, 13.3915634),
        southwest: LatLng(52.4943073, 13.4055383),
      ),
      id: 1,
      minZoom: 6,
      maxZoom: 18,
      mapStyleUrl: 'mapbox://styles/mapbox/streets-v11',
    );

    downloadOfflineRegionStream(offlineRegion, onEvent);

Location features

Android

Add the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in the application manifest android/app/src/main/AndroidManifest.xml to enable location features in an Android application:

<manifest ...
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Starting from Android API level 23 you also need to request it at runtime. This plugin does not handle this for you. The example app uses the flutter 'location' plugin for this.

iOS

To enable location features in an iOS application:

If you access your users' location, you should also add the following key to ios/Runner/Info.plist to explain why you need access to their location data:

xml ...
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>[Your explanation here]</string>

Mapbox recommends the explanation "Shows your location on the map and helps improve the map".

Contributing

  • Open issue regarding proposed change.
  • Repo owner will contact you there.
  • If your proposed change is approved, Fork this repo and do changes.
  • Open PR against latest dev branch. Add nice description in PR.
  • You're done!

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add mapbox_flutter

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  mapbox_flutter: ^1.0.0-dev.1.1

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:mapbox_flutter/mapbox_flutter.dart'; 

example/lib/main.dart

// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:mapbox_flutter_example/custom_marker.dart';
import 'package:mapbox_flutter_example/offline_regions.dart';
import 'package:mapbox_flutter_example/place_batch.dart';

import 'animate_camera.dart';
import 'annotation_order_maps.dart';
import 'full_map.dart';
import 'line.dart';
import 'local_style.dart';
import 'map_ui.dart';
import 'move_camera.dart';
import 'page.dart';
import 'place_circle.dart';
import 'place_source.dart';
import 'place_symbol.dart';
import 'place_fill.dart';
import 'scrolling_map.dart';

final List<ExamplePage> _allPages = <ExamplePage>[
  MapUiPage(),
  FullMapPage(),
  AnimateCameraPage(),
  MoveCameraPage(),
  PlaceSymbolPage(),
  PlaceSourcePage(),
  LinePage(),
  LocalStylePage(),
  PlaceCirclePage(),
  PlaceFillPage(),
  ScrollingMapPage(),
  OfflineRegionsPage(),
  AnnotationOrderPage(),
  CustomMarkerPage(),
  BatchAddPage(),
];

class MapsDemo extends StatelessWidget {
  //FIXME: Add your Mapbox access token here
  static const String ACCESS_TOKEN = "YOUR_TOKEN_HERE";

  void _pushPage(BuildContext context, ExamplePage page) async {
    if (!kIsWeb) {
      final location = Location();
      final hasPermissions = await location.hasPermission();
      if (hasPermissions != PermissionStatus.granted) {
        await location.requestPermission();
      }
    }
    Navigator.of(context).push(MaterialPageRoute<void>(
        builder: (_) => Scaffold(
              appBar: AppBar(title: Text(page.title)),
              body: page,
            )));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('MapboxFlutterMaps examples')),
      body: ListView.builder(
        itemCount: _allPages.length,
        itemBuilder: (_, int index) => ListTile(
          leading: _allPages[index].leading,
          title: Text(_allPages[index].title),
          onTap: () => _pushPage(context, _allPages[index]),
        ),
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(home: MapsDemo()));
} 

Download Details:

Author: BorisGautier

Source Code: https://github.com/BorisGautier/mapbox_flutter

#flutter #mapbox 

A New Flutter Plugin for Mapbox

A Mapbox GL Flutter Package for Creating Custom Maps

Flutter VTMaps GL

This Flutter plugin allows to show embedded interactive and customizable vector maps inside a Flutter widget. For the Android and iOS integration, we use mapbox-gl-native. For web, we rely on mapbox-gl-js. This project only supports a subset of the API exposed by these libraries.

screenshot.png

Running the example app

  • Install Flutter and validate its installation with flutter doctor
  • Clone the repository with git clone git@github.com:tobrun/flutter-mapbox-gl.git
  • Add a Mapbox access token to the example app (see next section)
  • Connect a mobile device or start an emulator, simulator or chrome
  • Locate the id of a the device with flutter devices
  • Run the app with cd flutter_mapbox/example && flutter packages get && flutter run -d {device_id}

Adding a VTMaps Access Token

This project uses VTMaps vector tiles, which requires a VTMaps account and a VTMaps access token. Obtain a free access token on your VTMaps account page.

Even if you do not use VTMaps vector tiles but vector tiles from a different source (like self-hosted tiles) with this plugin, you will need to specify any non-empty string as Access Token as explained below!

The recommended way to provide your access token is through the VTMaps constructor's accessToken parameter, which is available starting from the v0.8 release. Note that you should always use the same token throughout your entire app.

An alternative method to provide access tokens that was required until the v0.7 release is described in this wiki article.

Using the SDK in your project

This project is available on pub.dev, follow the instructions to integrate a package into your flutter application. For platform specific integration, use the flutter application under the example folder as reference.

Supported API

FeatureAndroidiOSWeb
Style
Camera
Gesture
User Location
Symbol
Circle
Line
Fill

Map Styles

Map styles can be supplied by setting the styleString in the MapOptions. The following formats are supported:

  1. Passing the URL of the map style. This can be one of the built-in map styles, also see MapboxStyles or a custom map style served remotely using a URL that start with 'http(s)://'
  2. Passing the style as a local asset. Create a JSON file in the assets and add a reference in pubspec.yml. Set the style string to the relative path for this asset in order to load it into the map.
  3. Passing the raw JSON of the map style. This is only supported on Android.

Offline Sideloading

Support for offline maps is available by "side loading" the required map tiles and including them in your assets folder.

Create your tiles package by following the guide available here.

Place the tiles.db file generated in step one in your assets directory and add a reference to it in your pubspec.yml file.

   assets:
     - assets/cache.db
  • Call installOfflineMapTiles when your application starts to copy your tiles into the location where Mapbox can access them. NOTE: This method should be called before the Map widget is loaded to prevent collisions when copying the files into place.
    try {
      await installOfflineMapTiles(join("assets", "cache.db"));
    } catch (err) {
      print(err);
    }

Location features

To enable location features in an Android application:

You need to declare the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in the AndroidManifest.xml and starting from Android API level 23 also request it at runtime. The plugin does not handle this for you. The example app uses the flutter 'location' plugin for this.

To enable location features in an iOS application:

If you access your users' location, you should also add the following key to your Info.plist to explain why you need access to their location data:

<key>NSLocationWhenInUseUsageDescription</key>
<string>[Your explanation here]</string>

Mapbox recommends the explanation "Shows your location on the map and helps improve the map".

Documentation

This README file currently houses all of the documentation for this Flutter project. Please visit mapbox.com/android-docs if you'd like more information about the Mapbox Maps SDK for Android and mapbox.com/ios-sdk for more information about the Mapbox Maps SDK for iOS.

Getting Help

  • Need help with your code?: Look for previous questions on the #mapbox tag — or ask a new question.
  • Have a bug to report? Open an issue. If possible, include a full log and information which shows the issue.
  • Have a feature request? Open an issue. Tell us what the feature should do and why you want the feature.

Contributing

We welcome contributions to this repository! If you're interested in helping build this Mapbox/Flutter integration, please read the contribution guide to learn how to get started.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add vtmap_gl

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  vtmap_gl: ^1.1.13

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:vtmap_gl/vtmap_gl.dart';

example/lib/main.dart

// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:mapbox_gl_example/full_map.dart';

import 'animate_camera.dart';
import 'full_map.dart';
import 'line.dart';
import 'map_ui.dart';
import 'move_camera.dart';
import 'page.dart';
import 'place_circle.dart';
import 'place_source.dart';
import 'place_symbol.dart';
import 'place_fill.dart';
import 'scrolling_map.dart';

final List<ExamplePage> _allPages = <ExamplePage>[
  MapUiPage(),
  FullMapPage(),
  AnimateCameraPage(),
  MoveCameraPage(),
  PlaceSymbolPage(),
  PlaceSourcePage(),
  LinePage(),
  PlaceCirclePage(),
  PlaceFillPage(),
  ScrollingMapPage(),
];

class MapsDemo extends StatelessWidget {
  //FIXME: Add your Mapbox access token here
//  static const String ACCESS_TOKEN = "pk.eyJ1IjoibGVwcHJvOTAiLCJhIjoiY2s4cG94N2hpMDU4MTNlcGdvY2gyamQwayJ9.LrwJ0gNZ6ncU7yLeaHKxAQ";
  static const String ACCESS_TOKEN = "6ht5fdbc-1996-4f54-87gf-5664f304f3d2";
  void _pushPage(BuildContext context, ExamplePage page) async {
    if (!kIsWeb) {
      final location = Location();
      final hasPermissions = await location.hasPermission();
      if (hasPermissions != PermissionStatus.GRANTED) {
        await location.requestPermission();
      }
    }
    Navigator.of(context).push(MaterialPageRoute<void>(
        builder: (_) => Scaffold(
              appBar: AppBar(title: Text(page.title)),
              body: page,
            )));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('MapboxMaps examples')),
      body: ListView.builder(
        itemCount: _allPages.length,
        itemBuilder: (_, int index) => ListTile(
            leading: _allPages[index].leading,
            title: Text(_allPages[index].title),
            onTap: () => _pushPage(context, _allPages[index])),
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(home: MapsDemo()));
}

Download Details:

Author: tobrun

Source Code: https://github.com/tobrun/flutter-mapbox-gl

#flutter #mapbox 

A Mapbox GL Flutter Package for Creating Custom Maps

A Flutter Package for Place Search using MapBox Api and For Static Map

About

This package provides easy api calls to MapBox Search API.

Also, it contains an static map image generator 😆.

Maki Icons can be used now in marker icon

As this package doesn't depend on Flutter SDK you cannot use the Colors class anymore on you Flutter project. Instead use map_box_search's Color.rgb constructor, passing the values as parameters:

var myColor = Colors.redAccent; //Flutter's Color class
var mapBoxColor = Color.rgb( myColor.red, myColor.green, myColor.blue);

Installing

First of all you must acquire an API key on the MapBox website https://www.mapbox.com/

Then, add the following to your pubspec.yaml file:

dependencies:
  mapbox_search: any

Examples

Reverse GeoCoding

var reverseGeoCoding = ReverseGeoCoding(
    apiKey: 'API Key',
    limit: 5,
);

Future<List<MapBoxPlace>> getPlaces() =>
  reverseGeoCoding.getAddress(
    Location(lat: 72.0, lng: 76.00),
);

Places Seach

var placesSearch = PlacesSearch(
    apiKey: 'API Key',
    limit: 5,
);

Future<List<MapBoxPlace>> getPlaces() =>
  placesSearch.getPlaces("New York");

Static Image

MapBoxStaticImage staticImage = MapBoxStaticImage(
    apiKey:
        "API Key");

Image With Polyline

    String getStaticImageWithPolyline() => staticImage.getStaticUrlWithPolyline(
      point1: Location(lat: 37.77343, lng: -122.46589),
      point2: Location(lat: 37.75965, lng: -122.42816),
      marker1: MapBoxMarker( markerColor: Colors.black, 
      markerLetter: MakiIcons.aerialway.value, 
      markerSize: MarkerSize.LARGE),
      marker2: MapBoxMarker(
          markerColor: Color.rgb(244, 67, 54),
          markerLetter: 'q',
          markerSize: MarkerSize.SMALL),
      height: 300,
      width: 600,
      zoomLevel: 16,
      style: MapBoxStyle.Mapbox_Dark,
      path: MapBoxPath(pathColor: Color.rgb(255, 0, 0), pathOpacity: 0.5,     pathWidth: 5),
      render2x: true);

Image with Marker

String getStaticImageWithMarker() => staticImage.getStaticUrlWithMarker(
  center: Location(lat: 37.77343, lng: -122.46589),
  marker: MapBoxMarker(
      markerColor: Color.rgb(0, 0, 0), markerLetter: 'p', markerSize: MarkerSize.LARGE),
  height: 300,
  width: 600,
  zoomLevel: 16,
  style: MapBoxStyle.Mapbox_Streets,
  render2x: true,
);

Image without Marker

String getStaticImageWithoutMarker() => staticImage.getStaticUrlWithoutMarker(
    center: Location(lat: 37.75965, lng: -122.42816),
    height: 300,
    width: 600,
    zoomLevel: 16,
    style: MapBoxStyle.Mapbox_Outdoors,
    render2x: true,
  );

Screenshots

Static Map Image

Static Map Image

Search Widget

DemoDemo

Use this package as a library

Depend on it

Run this command:

With Dart:

 $ dart pub add mapbox_search

With Flutter:

 $ flutter pub add mapbox_search

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  mapbox_search: ^3.0.1+1

Alternatively, your editor might support dart pub get or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:mapbox_search/mapbox_search.dart'; 

example/main.dart

import 'package:mapbox_search/mapbox_search.dart';

// import 'credentials.dart';
final MAPBOX_KEY = '';

Future<void> main() async {
  String apiKey = MAPBOX_KEY; //Set up a test api key before running

  await geoCoding(apiKey).catchError(print);
  await placesSearch(apiKey).catchError(print);
}

///Reverse GeoCoding sample call
Future geoCoding(String apiKey) async {
  var geoCodingService = ReverseGeoCoding(
    apiKey: apiKey,
    country: "BR",
    limit: 5,
  );

  var addresses = await geoCodingService.getAddress(Location(
    lat: -19.984846,
    lng: -43.946852,
  ));

  print(addresses);
}

///Places search sample call
Future placesSearch(String apiKey) async {
  var placesService = PlacesSearch(
    apiKey: apiKey,
    country: "BR",
    limit: 5,
  );

  var places = await placesService.getPlaces(
    "patio",
    location: Location(
      lat: -19.984634,
      lng: -43.9502958,
    ),
  );

  print(places);
}

Download Details:

Author: ketanchoyal

Source Code: https://github.com/ketanchoyal/mapbox_search

#flutter #mapbox 

A Flutter Package for Place Search using MapBox Api and For Static Map