Pro Yearly is on sale from $80 to $50! »

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

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

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

9987516c273a7874b12b742e7aef828f?s=128

Taro Matsuzawa aka. btm

October 13, 2019
Tweet

Transcript

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

    দᖒଠ࿠ @ Georepublic slide: https://hackmd.io/@smellman/foss4g-2019- kobe 1
  2. ࣗݾ঺հ ࣗݾ঺հ γχΞΤϯδχΞ @ Georepublic ίϛϡχςΟ͍Ζ͍Ζ΍ͬͯ·͢ OSGeo೔ຊࢧ෦ཧࣄ ೔ຊUNIXϢʔβձཧࣄ OpenStreetMap Foundation

    Japanϝϯόʔ ϒϨΠΫίΞΫϥελ 2
  3. FOSS4G 2019 NiigataͰYoutube഑৴୲౰Λ΍Γ· ͨ͠ɻ 3

  4. ഑৴෩ܠ ഑৴෩ܠ 4

  5. Youtube഑৴֓ཁ Youtube഑৴֓ཁ ϏσΦΧϝϥ HDMI to USB Thinkpad X220 ffmpeg (഑৴ιϑτ)

    htop (؂ࢹ) 5
  6. ຊ୊ ຊ୊ 6

  7. MapboxͷεϚʔτϑΥϯ޲͚ͷϥΠϒϥϦͷ঺հ Ͱ͢ɻ ஫ҙ: ࠓճ͸ mapbox gl js ͷ࿩Ͱ͸͋Γ·ͤ Μɻ ஫ҙ:

    SlideʹऩΊΔͨΊΠϯσϯτ͕গ่͠Ε͍ͯ Δ΋ͷ͕͋Γ·͢ɻ 7
  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
  9. Overview Overview Platform Development Languages iOS Swift/Objective-C Android Kotlin/Java Unity

    C# Xamarin C# React Native JavaScript Node.js JavaScript 9
  10. Mapbox GL Ecosystem Mapbox GL Ecosystem 10

  11. macOS޲͚ʹAppleScriptରԠͱ͔΍Γ͗͢ 11

  12. جຊػೳ جຊػೳ ʹରԠ ͨ·ʹରԠ͍ͯ͠ͳ͍࢓༷΋͋Δ ϓϥοτϑΥʔϜ͝ͱʹ࣮૷͞Ε͍ͯΔػೳ͕ ҧ͏ MapboxҎ֎Ͱ഑෍͍ͯ͠ΔStyle΋࢖͑Δ Smartphone޲͚ʹ͸ࣄલμ΢ϯϩʔυػೳ͕͋ Δ iOSʹ͸ϑΝΠϧͷ্ݶ͕͋ͬͨΓ͢Δ

    MapboxͷαʔϏεΛ࢖͏৔߹͸AccessToken͕ ඞཁ Mapbox Style Specification 12
  13. ࠓճ͸iOS/Android/React Nativeͷ࣮૷Λݟ͍ͯ͘ React Native͸ؒʹ߹͍·ͤΜͰͨ͠(ޙड़) 13

  14. Mapbox Maps SDK Mapbox Maps SDK for iOS for iOS

    Swift/Objective-CʹରԠͨ͠SDK StoryBoardͳͲͷGUI։ൃʹ΋ରԠ Πϯετʔϧํ๏͕͍͔ͭ͋͘Δ खಈ CocoaPad Carthage 14
  15. खಈͰߏங खಈͰߏங Mapbox.frameworkΛϓϩδΣΫτʹ௥Ճ Build phaseʹshellΛ௥Ճ Info.plistʹҎԼΛ௥Ճ MGLMapboxAccessToken ϩάΠϯͨ͠ঢ়ଶͰνϡʔτϦΞϧΛݟΔ ͱ͜ΕΛ࢖͑ͬͯग़ͯ͘Δ NSLocationWhenInUseUsageDescription

    15
  16. ஫ҙ఺ ஫ҙ఺ MapboxެࣜͷυΩϡϝϯτ͸هड़͕ݹ͘ɺ Mapbox.frameworkͷ௥Ճͷ࢓ํ͕ݹ͍XCodeͷ΍ Γํʹͳ͍ͬͯΔ 16

  17. Storyboardʹ௥Ճ Storyboardʹ௥Ճ Main.storyboardʹViewΛ௥Ճ͢Δ ΫϥεΛUIView͔ΒMGLMapViewʹมߋ͢Δ styleͷURLΛهड़ ͋ͱ͸࠲ඪͱ͔ೖΕ͓ͯ͘ͱࣗಈతʹͦͷ৔ ॴ΁ 17

  18. 18

  19. 19

  20. 20

  21. Marker(Annotation)Λ௥Ճ Marker(Annotation)Λ௥Ճ AnnotationΛ൓ԠͰ͖ΔΑ͏ʹDelegateΛ௥Ճ ViewController಺Ͱself.view.subviews͔Β MGLMapViewΛ୳ͯ͋ͬͨ͠ΒAnnotationΛ௥Ճ ͢Δ storyboardΛ࢖͏ͱExampleͱҧ͏΋ͷʹͳΓ ͕ͪͳͷͰ஫ҙ ϢʔςΟϦςΟؔ਺Λ࡞Δͱྑ͍͔΋ 21

  22. import UIKit import Mapbox class ViewController: UIViewController, MGLMapViewDelegate { ...

    } 22
  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
  24. // delegate func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) ->

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

  26. Mapbox Maps SDK Mapbox Maps SDK for Android for Android

    Java/KotlinʹରԠ جຊతʹίʔυΛॻ͘ελΠϧ Πϯετʔϧ͸GradleͰ΍ΔͷͰָ 26
  27. ؀ڥߏங ؀ڥߏங GradleͷઃఆΛapp/build.gradleʹॻ͖ࠐΉ build.gradle͕̎ͭ͋ΔͷͰ஫ҙ permissionͷઃఆΛAndroidManifest.xmlʹ௥Ճ ίʔυΛॻ͍࣮ͯ૷Λ͢Δ 27

  28. 28

  29. 29

  30. 30

  31. SymbolLayerΛ௥Ճ SymbolLayerΛ௥Ճ 8.x͔ΒMapView.addMarker͕depricatedʹ SymbolLayerͰ୅༻͢Δ MapboxMap.OnMapClickListenerͰΫϦοΫΠϕ ϯτΛϋϯυϦϯά͢Δ Ҏલͷmarkerͱ͔ͳΓҧ͏ߟ͑ํ 31

  32. ิ଍ ิ଍ LayerΛ࢖͏΍Γํࣗମ͸ϕʔεϚοϓͱॲཧΛ ڞ௨Խ͢Δͱ͍͏ߟ͑ํͱࢥΘΕΔ Mapboxతʹ͸ਖ਼͍͠΍Γํ iOS͸Androidͱಉ࣮͡૷͕Ͱ͖Δ͕ͬͪ͜͸· ͩmarkerͷॲཧ͸depricatedʹͳ͍ͬͯͳ͍ ͍ͣΕͳΔͱࢥΘΕΔ ͜ͷ࢓༷Λௐ΂ΔͨΊʹReact Nativeͷ࣮૷ௐ΂

    ͖Ε·ͤΜͰͨ͠ 32
  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
  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
  35. ߟ͑ํͱͯ͠͸Mapbox StudioͰSymbolLayerΛ ొ࿥͢ΔྲྀΕʹ͍ۙ a. ΞΠίϯΛొ࿥ b. ιʔεΛొ࿥ c. SymbolLayerΛొ࿥ͯ͠ɺͦͷଐੑʹ iconImageΛ͚ͭΔ

    ݩͷΞΠίϯը૾͕ແ͍ͷͰࣗ෼Ͱ༻ҙ͢Δඞ ཁ͕͋Δ 35
  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
  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
  38. 38

  39. 39

  40. Ͱ͸iOSͰ͸͜ͷॻ͖ํͲ͏͢Δͷʁ 40

  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
  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
  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
  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
  45. @objc @IBAction func handleMapTap( sender: UITapGestureRecognizer) { if sender.state ==

    .ended { let point = sender.location(in: sender.view!) let layerIdentifiers: Set = ["kobe_layer"] 45
  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
  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
  48. 48

  49. 49

  50. ·ͱΊ ·ͱΊ AndroidͷMapbox Maps SDK 8.x͔ΒmarkerΛ௥ Ճ͢Δ΋ͷ͕࢖͑ͳ͘ͳͬͨ LayerΛ࢖͓͏ͱ͍͏ํ޲ੑ iOS͸·ͩଘࡏ͢Δ͕ɺLayerΛ࢖͏ํ๏΋͋Δ ࠓޙ͸LayerΛҙࣝͨ͠ϓϩάϥϛϯά͕ඞཁ

    ReactNativeͰ΋ਪ঑͞Ε͍ͯΔ 50
  51. ͓ΘΓ ͓ΘΓ GitHub Twitter 51