Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Mapbox Maps SDKでスマートフォンアプリ開発
Search
Taro Matsuzawa aka. btm
October 13, 2019
Programming
1
1.8k
Mapbox Maps SDKでスマートフォンアプリ開発
FOSS4G 2019 Kobe KANSAIにて発表したプレゼンテーションを実験的にPDF化したものです
Taro Matsuzawa aka. btm
October 13, 2019
Tweet
Share
More Decks by Taro Matsuzawa aka. btm
See All by Taro Matsuzawa aka. btm
OpenLayers ext TypeScript declarationの開発
smellman
0
580
平成生まれのためのUNIX&IT歴 史講座 ~番外編~
smellman
2
520
掛川城の点群データをiTownsで表示しよう
smellman
0
310
そのJavascript、全部TypeScriptにしちゃえ
smellman
1
220
大容量SSDとOpenStreetMap
smellman
0
140
MapLibreとtile.openstretmap.jpで始めるベクトル地図プログラミング
smellman
1
600
国内向けタイルサーバの構築と運用について
smellman
0
1.4k
Python/Javascriptで読む点群
smellman
1
5.1k
日本のCommunity向け タイルサーバの現状
smellman
0
2.7k
Other Decks in Programming
See All in Programming
Processing Gem ベースの、2D レトロゲームエンジンの開発
tokujiros
2
100
AIでLINEスタンプを作ってみた
eycjur
1
210
私の後悔をAWS DMSで解決した話
hiramax
4
170
『リコリス・リコイル』に学ぶ!! 〜キャリア戦略における計画的偶発性理論と変わる勇気の重要性〜
wanko_it
1
610
実用的なGOCACHEPROG実装をするために / golang.tokyo #40
mazrean
1
110
AIコーディングAgentとの向き合い方
eycjur
0
240
ライブ配信サービスの インフラのジレンマ -マルチクラウドに至ったワケ-
mirrativ
2
270
🔨 小さなビルドシステムを作る
momeemt
2
610
TanStack DB ~状態管理の新しい考え方~
bmthd
2
360
DockerからECSへ 〜 AWSの海に出る前に知っておきたいこと 〜
ota1022
5
1.8k
FindyにおけるTakumi活用と脆弱性管理のこれから
rvirus0817
0
200
物語を動かす行動"量" #エンジニアニメ
konifar
14
5.6k
Featured
See All Featured
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
19k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
11
1k
4 Signs Your Business is Dying
shpigford
184
22k
Designing Experiences People Love
moore
142
24k
The Invisible Side of Design
smashingmag
301
51k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.4k
Into the Great Unknown - MozCon
thekraken
40
2k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Transcript
Mapbox Maps SDK Mapbox Maps SDK ͰεϚʔτϑΥϯΞ ͰεϚʔτϑΥϯΞ ϓϦ։ൃ ϓϦ։ൃ
দᖒଠ @ Georepublic slide: https://hackmd.io/@smellman/foss4g-2019- kobe 1
ࣗݾհ ࣗݾհ γχΞΤϯδχΞ @ Georepublic ίϛϡχςΟ͍Ζ͍Ζͬͯ·͢ OSGeoຊࢧ෦ཧࣄ ຊUNIXϢʔβձཧࣄ OpenStreetMap Foundation
Japanϝϯόʔ ϒϨΠΫίΞΫϥελ 2
FOSS4G 2019 NiigataͰYoutube৴୲ΛΓ· ͨ͠ɻ 3
৴෩ܠ ৴෩ܠ 4
Youtube৴֓ཁ Youtube৴֓ཁ ϏσΦΧϝϥ HDMI to USB Thinkpad X220 ffmpeg (৴ιϑτ)
htop (ࢹ) 5
ຊ ຊ 6
MapboxͷεϚʔτϑΥϯ͚ͷϥΠϒϥϦͷհ Ͱ͢ɻ ҙ: ࠓճ mapbox gl js ͷͰ͋Γ·ͤ Μɻ ҙ:
SlideʹऩΊΔͨΊΠϯσϯτ͕গ่͠Ε͍ͯ Δͷ͕͋Γ·͢ɻ 7
Mapbox Maps SDK Mapbox Maps SDK Mapbox͕ग़͍ͯ͠ΔωΠςΟϒ͚SDK Maps SDKͱུ͍ͯ͠Δ ެࣜαΠτͰiOS/Android/UnityʹରԠ
ࠓճiOSͱAndroidʹ͍͓ͭͯ Github্ʹXamarin/ReactNative/Node.jsͳͲ Node.jsαʔόαΠυϨϯμϦϯάʹར༻ ίΞ෦C++Ͱ࡞ 8
Overview Overview Platform Development Languages iOS Swift/Objective-C Android Kotlin/Java Unity
C# Xamarin C# React Native JavaScript Node.js JavaScript 9
Mapbox GL Ecosystem Mapbox GL Ecosystem 10
macOS͚ʹAppleScriptରԠͱ͔Γ͗͢ 11
جຊػೳ جຊػೳ ʹରԠ ͨ·ʹରԠ͍ͯ͠ͳ͍༷͋Δ ϓϥοτϑΥʔϜ͝ͱʹ࣮͞Ε͍ͯΔػೳ͕ ҧ͏ MapboxҎ֎Ͱ͍ͯ͠ΔStyle͑Δ Smartphone͚ʹࣄલμϯϩʔυػೳ͕͋ Δ iOSʹϑΝΠϧͷ্ݶ͕͋ͬͨΓ͢Δ
MapboxͷαʔϏεΛ͏߹AccessToken͕ ඞཁ Mapbox Style Specification 12
ࠓճiOS/Android/React Nativeͷ࣮Λݟ͍ͯ͘ React Nativeؒʹ߹͍·ͤΜͰͨ͠(ޙड़) 13
Mapbox Maps SDK Mapbox Maps SDK for iOS for iOS
Swift/Objective-CʹରԠͨ͠SDK StoryBoardͳͲͷGUI։ൃʹରԠ Πϯετʔϧํ๏͕͍͔ͭ͋͘Δ खಈ CocoaPad Carthage 14
खಈͰߏங खಈͰߏங Mapbox.frameworkΛϓϩδΣΫτʹՃ Build phaseʹshellΛՃ Info.plistʹҎԼΛՃ MGLMapboxAccessToken ϩάΠϯͨ͠ঢ়ଶͰνϡʔτϦΞϧΛݟΔ ͱ͜ΕΛ͑ͬͯग़ͯ͘Δ NSLocationWhenInUseUsageDescription
15
ҙ ҙ MapboxެࣜͷυΩϡϝϯτهड़͕ݹ͘ɺ Mapbox.frameworkͷՃͷํ͕ݹ͍XCodeͷ Γํʹͳ͍ͬͯΔ 16
StoryboardʹՃ StoryboardʹՃ Main.storyboardʹViewΛՃ͢Δ ΫϥεΛUIView͔ΒMGLMapViewʹมߋ͢Δ styleͷURLΛهड़ ͋ͱ࠲ඪͱ͔ೖΕ͓ͯ͘ͱࣗಈతʹͦͷ ॴ 17
18
19
20
Marker(Annotation)ΛՃ Marker(Annotation)ΛՃ AnnotationΛԠͰ͖ΔΑ͏ʹDelegateΛՃ ViewControllerͰself.view.subviews͔Β MGLMapViewΛ୳ͯ͋ͬͨ͠ΒAnnotationΛՃ ͢Δ storyboardΛ͏ͱExampleͱҧ͏ͷʹͳΓ ͕ͪͳͷͰҙ ϢʔςΟϦςΟؔΛ࡞Δͱྑ͍͔ 21
import UIKit import Mapbox class ViewController: UIViewController, MGLMapViewDelegate { ...
} 22
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
// delegate func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) ->
MGLAnnotationView? { return nil } func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool { return true } 24
25
Mapbox Maps SDK Mapbox Maps SDK for Android for Android
Java/KotlinʹରԠ جຊతʹίʔυΛॻ͘ελΠϧ ΠϯετʔϧGradleͰΔͷͰָ 26
ڥߏங ڥߏங GradleͷઃఆΛapp/build.gradleʹॻ͖ࠐΉ build.gradle͕̎ͭ͋ΔͷͰҙ permissionͷઃఆΛAndroidManifest.xmlʹՃ ίʔυΛॻ͍࣮ͯΛ͢Δ 27
28
29
30
SymbolLayerΛՃ SymbolLayerΛՃ 8.x͔ΒMapView.addMarker͕depricatedʹ SymbolLayerͰ༻͢Δ MapboxMap.OnMapClickListenerͰΫϦοΫΠϕ ϯτΛϋϯυϦϯά͢Δ Ҏલͷmarkerͱ͔ͳΓҧ͏ߟ͑ํ 31
ิ ิ LayerΛ͏ΓํࣗମϕʔεϚοϓͱॲཧΛ ڞ௨Խ͢Δͱ͍͏ߟ͑ํͱࢥΘΕΔ Mapboxతʹਖ਼͍͠Γํ iOSAndroidͱಉ࣮͕͡Ͱ͖Δ͕ͬͪ͜· ͩmarkerͷॲཧdepricatedʹͳ͍ͬͯͳ͍ ͍ͣΕͳΔͱࢥΘΕΔ ͜ͷ༷ΛௐΔͨΊʹReact Nativeͷ࣮ௐ
͖Ε·ͤΜͰͨ͠ 32
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
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
ߟ͑ํͱͯ͠Mapbox StudioͰSymbolLayerΛ ొ͢ΔྲྀΕʹ͍ۙ a. ΞΠίϯΛొ b. ιʔεΛొ c. SymbolLayerΛొͯ͠ɺͦͷଐੑʹ iconImageΛ͚ͭΔ
ݩͷΞΠίϯը૾͕ແ͍ͷͰࣗͰ༻ҙ͢Δඞ ཁ͕͋Δ 35
@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
ॲཧͷதͷྫ 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
39
ͰiOSͰ͜ͷॻ͖ํͲ͏͢Δͷʁ 40
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
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
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
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
@objc @IBAction func handleMapTap( sender: UITapGestureRecognizer) { if sender.state ==
.ended { let point = sender.location(in: sender.view!) let layerIdentifiers: Set = ["kobe_layer"] 45
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
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
49
·ͱΊ ·ͱΊ AndroidͷMapbox Maps SDK 8.x͔ΒmarkerΛ Ճ͢Δͷ͕͑ͳ͘ͳͬͨ LayerΛ͓͏ͱ͍͏ํੑ iOS·ͩଘࡏ͢Δ͕ɺLayerΛ͏ํ๏͋Δ ࠓޙLayerΛҙࣝͨ͠ϓϩάϥϛϯά͕ඞཁ
ReactNativeͰਪ͞Ε͍ͯΔ 50
͓ΘΓ ͓ΘΓ GitHub Twitter 51