Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

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

Taro Matsuzawa aka. btm

October 13, 2019
Tweet

More Decks by Taro Matsuzawa aka. btm

Other Decks in Programming

Transcript

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

    দᖒଠ࿠ @ Georepublic slide: https://hackmd.io/@smellman/foss4g-2019- kobe 1
  2. 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. Mapbox Maps SDK Mapbox Maps SDK for iOS for iOS

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

  5. 19

  6. 20

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

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

  10. Mapbox Maps SDK Mapbox Maps SDK for Android for Android

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

  12. 29

  13. 30

  14. 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
  15. 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
  16. @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
  17. ॲཧͷத਎ͷྫ 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
  18. 38

  19. 39

  20. 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
  21. 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
  22. 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
  23. 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
  24. @objc @IBAction func handleMapTap( sender: UITapGestureRecognizer) { if sender.state ==

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

  28. 49