Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Mapbox GL-based Mapbox Static API #9

Closed
1ec5 opened this issue Mar 30, 2016 · 21 comments · Fixed by #54
Closed

Upgrade to Mapbox GL-based Mapbox Static API #9

1ec5 opened this issue Mar 30, 2016 · 21 comments · Fixed by #54

Comments

@1ec5
Copy link
Contributor

1ec5 commented Mar 30, 2016

This library uses the classic Mapbox Static API. We should upgrade it to the newer Mapbox Static API that’s based on Mapbox GL. The new API supports options like rotation and pitch, although it lacks support for markers and overlays.

/cc @friedbunny @bsudekum

@SCasarotto
Copy link

I am looking to use this library with the non-classic Mapbox style. Is there a quick workaround to use the current code with Mapbox GL? If not, I will be awaiting the update and will implement it the moment it is released.

Thanks!

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 5, 2016

Hi @SCasarotto, just double checking: are you interested in getting static images for newer Mapbox GL styles, or would you like to display raster, non-GL styles in the Mapbox iOS or Android SDK? If the latter, please take a look at the following examples: https://www.mapbox.com/ios-sdk/examples/raster-styles/ https://www.mapbox.com/android-sdk/custom-raster-style/

@SCasarotto
Copy link

Nope I have built up a pretty complex ios project on the standard maps but i am looking for the static images for the new Mapbox GL. I was using the mapViews in a UITable how ever that is extremely memory intensive and was going to convert to static images instead (since that is all the maps were function as anyways) .

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 5, 2016

Got it. Thanks for the clarification. For now, a workaround would be to call the REST API directly using NSURLSession or NSURLConnection. Here's documentation for the REST API: note the "cURL" example.

@SCasarotto
Copy link

Great that is what I was planning to do.We have some other milestones that are higher on the priority list but when I get back to this if this hasn't been updated then I will start to write my own. If I do write something similar to the current one for the new GL I will be sure to share it with you.

Thanks for all your work!

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 5, 2016

In case it helps, I dug around and found some code that we're using in an internal testbed application to talk to the Static API. Here's the entire Swift implementation, which does nothing but construct a URL. I recommend using it with SDWebImage.

@SCasarotto
Copy link

Awesome. Thanks I am part way through rewriting this one. (Got motivated haha). Thanks for that information.

@SCasarotto
Copy link

I have no idea how to send you this in the best way to review and add to the git but I got this working:

import CoreLocation
import Foundation
import UIKit

public class MapboxStaticMap{

    private let requestURLStringBase = "https://api.mapbox.com/styles/v1/"

    private(set) var requestURL: NSURL

    public var image: UIImage? {
        get {
            if let data = NSData(contentsOfURL: self.requestURL) {
                return UIImage(data: data)
            } else {
                return nil
            }
        }
    }

    public func imageWithCompletionHandler(handler: (UIImage? -> Void)) {
        let task = NSURLSession.sharedSession().dataTaskWithURL(requestURL, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) in
            let image = UIImage(data: data!)
            dispatch_async(dispatch_get_main_queue()) {
                handler(image)
            }
        })
        task.resume()
    }

    init(username       : String,
         styleID        : String,
         center         : CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0, longitude: 0),
         zoom           : Int = 0,
         bearing        : Int = 0,
         pitch          : Int = 0,
         size           : CGSize,
         retina         : Bool = false,
         accessToken    : String,
         attribution    : Bool = true,
         logo           : Bool = true
        ){

        let maximumDimension: CGFloat = 1280

        var requestURLString = requestURLStringBase
        requestURLString += username
        requestURLString += "/"
        requestURLString += styleID
        requestURLString += "/static/"
        requestURLString += String(center.longitude)
        requestURLString += ","
        requestURLString += String(center.latitude)
        requestURLString += ","
        requestURLString += String(zoom)
        requestURLString += ","
        requestURLString += String(bearing)
        requestURLString += ","
        requestURLString += String(pitch)
        requestURLString += "/"
        requestURLString += String(Int(min(round(size.width), maximumDimension)))
        requestURLString += "x"
        requestURLString += String(Int(min(round(size.height), maximumDimension)))
        requestURLString += (retina ? "@2x" : "")
        requestURLString += "?access_token="
        requestURLString += accessToken
        requestURLString += "&attribution="
        requestURLString += (attribution ? "true" : "false")
        requestURLString += "&logo="
        requestURLString += (logo ? "true" : "false")

        requestURL = NSURL(string: requestURLString)!
    }
}

edit: added the attribution and logo variables

@SCasarotto
Copy link

I would love to walk through what ever standard steps it takes to contribute to this repo and also feel free to clean up what I have with the code you guys already wrote. I kind of enjoyed rewriting it. :)

Thanks for the guidence

@SCasarotto
Copy link

Its worth noting that

let scaleFactor = Int(round(UIScreen.mainScreen().scale))
let scaleSuffix = scaleFactor != 1 ? "@\(scaleFactor)x" : ""

doesn't work on 6s plus (@3x). Thats why i left mine as a bool with just the @2x.

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 5, 2016

Thanks for the code! I think the way forward for this project is to migrate it to RequestKit, similar to what we did in MapboxGeocoder.swift and MapboxDirections.swift recently. That would normally be overkill for a library this simple, but keeping the libraries’ architectures similar will allow us to eventually create a unified library that talks to all of Mapbox’s REST APIs.

doesn't work on 6s plus (@​3x)

Ah, that makes sense. The Static API uses mapbox-gl-native under the hood, so supporting @​3x in the API would be blocked by mapbox/mapbox-gl-native#1008.

@SCasarotto
Copy link

Okay sounds great. For now I will be using this code but will keep an eye on these projects to stay up to date.

@SCasarotto
Copy link

Last question, in the api there are attribution and logo parameters. What is the syntax for adjusting those?
Also, in the static api call examples you guys don't mention the AccessToken but when I manually make a static image through the studio it has it in the URL. Is it optional or is the documentation incomplete?

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 5, 2016

The attribution and logo parameters only toggle those elements on and off. They’re currently hardcoded to say “© OpenStreetMap” and “Mapbox”, respectively, and can’t be modified. (Mapbox maps require attribution for legal reasons.)

access_token is required. You can get an access token in Studio. The access token ties individual requests to your Mapbox account, which is important both to track map views for billing purposes and to deter others from hotlinking your custom styles. (Note that the iOS SDK counts active users rather than map views.)

@SCasarotto
Copy link

Right I understand not being able to adjust what they say however you guys do offer whitelabeling as a service in your enterprise plan. In the api it looks like you can toggle them. Is that simply done by adding " {lon},{lat},{zoom},{bearing},{pitch}/{width}x{height}{@2x}/false,false" or something?

Also I understand the use of the access token however the examples provided look like :

/styles/v1/{username}/{style_id}/static/{lon},{lat},{zoom},{bearing},{pitch}/{width}x{height}{@2x}

curl https://api.mapbox.com/styles/v1/mapbox/streets-v8/static/-122.4241,37.78,14.25,0,60/600x600

curl https://api.mapbox.com/styles/v1/mapbox/streets-v8/static/0,20,3,20/600x600

which lack the ?access_token= part of the URL. Should that be in the documentation?

@1ec5
Copy link
Contributor Author

1ec5 commented Apr 5, 2016

attribution and logo are parameters to the URL, so they’d be appended just like the access_token parameter, i.e., attribution=false&logo=false. The access_token parameter is covered in this section of the API documentation.

@SCasarotto
Copy link

Great thanks!

@1ec5
Copy link
Contributor Author

1ec5 commented May 12, 2016

Following all the changes in #19, we’re in a good spot to add support for the new Mapbox GL–based Static API to this framework (if it makes sense to combine it with the existing framework).

I think it makes sense to support both APIs in some form until the new API supports overlays. The cleanest way would be:

  • SnapshotOptions becomes ClassicSnapshotOptions.
  • ClassicSnapshotOptions conforms to a new protocol, URLRequestConvertible, that requires path and params.
  • A new SnapshotOptions conforms to URLRequestConvertible with all the parameters that the new API requires.
  • Some assertions in Snapshot.init(options:accessToken:host:) move into ClassicSnapshotOptions.

/cc @bsudekum

@incanus
Copy link
Contributor

incanus commented Nov 10, 2016

Just as a freshness update to this ticket, the new GL-based API at https://www.mapbox.com/api-documentation/#static still does not support overlays. I'm more in favor of sitting on this ticket until such time as they are supported.

Keep in mind that https://github.com/mapbox/MapboxTableViewDemo shows an example of using GL native (i.e. the base of the mobile SDKs) as non-interactive map views, including efficiently reusing this in table views, as a way to leverage GL technology efficiently, with support for overlays, too.

@1ec5
Copy link
Contributor Author

1ec5 commented Feb 28, 2017

The Mapbox-GL-based Static API now supports overlays with largely the same parameters as the classic Static API, so supporting both APIs simultaneously should be pretty straightforward.

@1ec5 1ec5 self-assigned this Mar 4, 2017
@1ec5
Copy link
Contributor Author

1ec5 commented Mar 6, 2017

This is finally happening in #54.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants