Mapbox Maps SDKでスマートフォンアプリ開発

Mapbox Maps SDKでスマートフォンアプリ開発

FOSS4G 2019 Kobe KANSAIにて発表したプレゼンテーションを実験的にPDF化したものです

9987516c273a7874b12b742e7aef828f?s=128

Taro Matsuzawa aka. btm

October 13, 2019
Tweet

Transcript

  1. 1.

    Mapbox Maps SDK Mapbox Maps SDK ͰεϚʔτϑΥϯΞ ͰεϚʔτϑΥϯΞ ϓϦ։ൃ ϓϦ։ൃ

    দᖒଠ࿠ @ Georepublic slide: https://hackmd.io/@smellman/foss4g-2019- kobe 1
  2. 8.

    Mapbox Maps SDK Mapbox Maps SDK Mapbox͕ग़͍ͯ͠ΔωΠςΟϒ޲͚SDK Maps SDKͱུ͍ͯ͠Δ ެࣜαΠτͰ͸iOS/Android/UnityʹରԠ

    ࠓճ͸iOSͱAndroidʹ͍͓ͭͯ࿩ Github্ʹ͸Xamarin/ReactNative/Node.jsͳͲ Node.js͸αʔόαΠυϨϯμϦϯάʹར༻ ίΞ෦෼͸C++Ͱ࡞੒ 8
  3. 9.
  4. 14.

    Mapbox Maps SDK Mapbox Maps SDK for iOS for iOS

    Swift/Objective-CʹରԠͨ͠SDK StoryBoardͳͲͷGUI։ൃʹ΋ରԠ Πϯετʔϧํ๏͕͍͔ͭ͋͘Δ खಈ CocoaPad Carthage 14
  5. 18.

    18

  6. 19.

    19

  7. 20.

    20

  8. 23.

    override func viewDidLoad() { super.viewDidLoad() for v in self.view.subviews {

    if let item = v as? MGLMapView { item.delegate = self let hello = MGLPointAnnotation() hello.coordinate = CLLocationCoordinate2D(...) hello.title = "..." hello.subtitle = "..." item.addAnnotation(hello) } } } 23
  9. 24.

    // delegate func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) ->

    MGLAnnotationView? { return nil } func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool { return true } 24
  10. 25.

    25

  11. 26.

    Mapbox Maps SDK Mapbox Maps SDK for Android for Android

    Java/KotlinʹରԠ جຊతʹίʔυΛॻ͘ελΠϧ Πϯετʔϧ͸GradleͰ΍ΔͷͰָ 26
  12. 28.

    28

  13. 29.

    29

  14. 30.

    30

  15. 33.

    public void onMapReady(@NonNull final MapboxMap mapboxMap) { this.mapboxMap = mapboxMap;

    this.features = new ArrayList<>(); Feature f = Feature.fromGeometry( Point.fromLngLat(135.19890, 34.68505)); f.addStringProperty(TITLE_PROP, "KITTO"); f.addStringProperty(DESCRIPTION_PROP, "Welcome to FOSS4G 2019 Kansai/Kobe"); this.features.add(f); ... 1 2 3 4 5 6 7 8 9 10 11 33
  16. 34.

    mapboxMap.setStyle( new Style.Builder().fromUri("...") .withImage(ICON_ID, BitmapFactory.decodeResource( MainActivity.this.getResources(), R.drawable.red_marker)) .withSource(new GeoJsonSource(SOURCE_ID, FeatureCollection.fromFeatures(this.features)))

    .withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID) .withProperties(PropertyFactory.iconImage(ICON_ID), PropertyFactory.iconAllowOverlap(true), PropertyFactory.iconOffset(new Float[]{0f, -9f})) ), new Style.OnStyleLoaded() {...}); mapboxMap.addOnMapClickListener(this); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 34
  17. 36.

    @Override public boolean onMapClick(@NonNull LatLng point) { PointF screenPoint =

    mapboxMap.getProjection() .toScreenLocation(point); List<Feature> features = mapboxMap .queryRenderedFeatures(screenPoint, LAYER_ID); if (!features.isEmpty()) { // ͜͜ʹ۩ମతͳॲཧΛॻ͘ return true; } return false; } 1 2 3 4 5 6 7 8 9 10 11 12 36
  18. 37.

    ॲཧͷத਎ͷྫ Feature f = features.get(0); AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

    builder .setMessage(f.getStringProperty(DESCRIPTION_PROP)) .setTitle(f.getStringProperty(TITLE_PROP)); AlertDialog dialog = builder.create(); dialog.show(); 1 2 3 4 5 6 7 8 37
  19. 38.

    38

  20. 39.

    39

  21. 41.

    func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) { let markerImage

    = #imageLiteral(resourceName: "marker") mapView.style?.setImage(markerImage, forName: "marker-icon") let coordinate = CLLocationCoordinate2D(latitude: 34.68505, longitude: 135.19890) 41
  22. 42.

    let hello = MGLPointFeature() hello.coordinate = coordinate hello.attributes = [

    "name": "KITTO", "description": "Welcome to FOSS4G 2019 Kansai/Kobe" ] let source = MGLShapeSource( identifier: "kobe_source", features: [hello], options: nil) mapView.style?.addSource(source) 42
  23. 43.

    let symbols = MGLSymbolStyleLayer( identifier: "kobe_layer", source: source) symbols.iconImageName =

    NSExpression( forConstantValue: "marker-icon") symbols.iconAllowsOverlap = NSExpression( forConstantValue: true) symbols.iconOffset = NSExpression( forConstantValue: CGVector(dx: 0, dy: -9)) mapView.style?.addLayer(symbols) } 43
  24. 44.

    if let item = v as? MGLMapView { item.delegate =

    self mapView = item let singleTap = UITapGestureRecognizer( target: self, action: #selector(handleMapTap(sender:))) for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer { singleTap.require(toFail: recognizer) } mapView.addGestureRecognizer(singleTap) } 44
  25. 45.

    @objc @IBAction func handleMapTap( sender: UITapGestureRecognizer) { if sender.state ==

    .ended { let point = sender.location(in: sender.view!) let layerIdentifiers: Set = ["kobe_layer"] 45
  26. 46.

    for feature in mapView.visibleFeatures( at: point, styleLayerIdentifiers: layerIdentifiers) where feature

    is MGLPointFeature { guard let selectedFeature = feature as? MGLPointFeature else { fatalError("...") } showCallout(feature: selectedFeature) return } } } 46
  27. 47.

    func showCallout(feature: MGLPointFeature) { let dialog: UIAlertController = UIAlertController( title:

    feature.attributes["name"] as? String, message: feature.attributes["description"] as? String, preferredStyle: UIAlertController.Style.alert) let action = UIAlertAction(title: "ด͡Δ", style: UIAlertAction.Style.default, handler: nil) dialog.addAction(action) self.present(dialog, animated: true, completion: nil) } 47
  28. 48.

    48

  29. 49.

    49