Adding Mapbox to layout container


#1

Hi,
I’m using the Mapbox plugin and I’ve been able to create a map programmatically using the example code in the readme file. This appears to create the map using the entire screen.

What I want to do is insert the map inside a StackLayout container (the one with id=“map” in the XML snippet below). I assumed I’d be able to get a reference to the StackLayout and then use its AddChild() method to add the Mapbox map to it. This doesn’t seem to work, however, as the map is still consuming the entire screen.

I’m assuming this must be possible as you can if the map is declared inside a container using XML. Perhaps I’m not passing the correct mapbox object reference to the addChild() method? Can anybody advise what I might be doing wrong? An extract of my code is below.

function onPageLoaded(args) {
page = args.object;
var sl = View.getViewById(page, “map”);

var mapbox = new Mapbox.Mapbox();
mapbox.show({
    // Mapbox properties here
}).then(
    function(showResult) {
        sl.addChild(mapbox);
    }
)

}


#2

What’s the version of plugin you are using? Did you try MapboxView using example in readme.


#3

Hi,
I was using v3.2.0 of the plugin. Your email prompted me to check for an update and I just tried v3.3.0 but the map still consumes the entire screen.

When you ask ‘Did you try MapboxView using example in readme’, I did try creating the map using the XML MapView example and that works fine. For my app, though, I need to create the map programmatically inside a child StackLayout container.


#4

Hi,
I just re-read your reply and wondered if I’m importing the plugin incorrectly. At the moment I’m using…

var Mapbox = require(“nativescript-mapbox”); // Import plugin

var mapbox = new Mapbox.Mapbox(); // Create new mapbox object

mapbox.show({…}) // Create the map

So perhaps I’m not using the MapboxView method when I create the map programatically?


#5

I don’t think you are using MapboxView still when doing programatically. Try,

var mapboxView = new Mapbox.MapboxView();
mapboxView.height = 300; // whatever height you may want
stackLayout.addChild(mapboxView);

#6

Hi,
Thanks for your help on this. You’re right - I wasn’t using the MapboxView constructor before although I can’t actually get a map to display using it. I’ve stripped the code right back to the XML and JS below and get the error ‘mapboxView.show is not a function’. Can you see any mistakes?

XML

<Page 
    navigatingTo="onPageLoaded"
    xmlns="http://www.nativescript.org/tns.xsd">
    <StackLayout orientation="vertical">
        <Label text="This text appears above map"/>
        <StackLayout id="map" orientation="vertical"/>
        <Label text="This text appears below map"/>
    </StackLayout>
</Page>

JS

var View = require("ui/core/view");
var Mapbox = require("nativescript-mapbox");
var Platform = require("platform");

function onPageLoaded(args) {
    var isIOS = Platform.device.os === Platform.platformNames.ios;
    var page = args.object;
    var stackLayout = View.getViewById(page, "map"); 

    var mapboxView = new Mapbox.MapboxView();
    mapboxView.height = 300;    
    stackLayout.addChild(mapboxView);

    mapboxView.show({
        accessToken: 'My API token',
        style: 'streets',
        margins: {
            left: 40,
            right: 40,
            top: 0,
            bottom: isIOS ? 50: 0 
        },        
        center: {
            lat: 52.3732160, 
            lng: 4.8941680 
        },
        zoomLevel: 9.25, 
        showUserLocation: true, 
        hideAttribution: false, 
        hideLogo: false, 
        hideCompass: false, 
        disableRotation: false, 
        disableScroll: false, 
        disableZoom: false        
    }).then(
        function(showResult) {
            console.log("Mapbox show done. Native object received: " + (showResult.ios ? showResult.ios : showResult.android));
        },
        function(error) {
            console.log("mapbox show error: " + error);
        }
    )
}

exports.onPageLoaded = onPageLoaded;

#7

Exactly, you don’t have to call mapboxView.show, it’s undefined. Everything should be accessed as properties, like mapboxView. accessToken / mapboxView.zoomLevel.


#8

Thanks - I can now show a map inside a layout container. The only thing I can’t get to work now is showing markers. Should the ‘markers’ property still work with MapboxView? The code below shows my map but not the marker.


var mapboxView = new Mapbox.MapboxView();
    mapboxView.height = 300;
    mapboxView.accessToken = "my api token";
    mapboxView.mapStyle = "streets";
    mapboxView.latitude = 52.3702160;
    mapboxView.longitude = 4.8951680;
    mapboxView.zoomLevel = 9.25;
    mapboxView.showUserLocation = false;
    mapboxView.markers = [
        { 
            id: 1,
            lat: 52.3702160, 
            lng: 4.8951680, 
            title: 'Nice location', 
            subtitle: 'Really really nice location',
            icon: "res://green_marker",
            onTap: function(args) { console.log("Marker " + args.id + " tapped"); }
        }
    ];
    stackLayout.addChild(mapboxView);

#9

Please refer the readme of plugin, when you use MapboxView, you have to wait for mapReady event on which you will call any methods like addMarker / setViewport.


#10

Thanks. I did try that earlier but I must have got the syntax wrong. I’ve now sorted that and I can get the onMapReady function to fire.

Previously, when I was generating the map in XML, I was able to get a Mapbox reference in the onMapReady handler and use the AddMarkers method as follows…

function onMapReady(args) {   
    args.map.addMarkers(...)

Now, though, when I generate the map in code (see below), I’m guessing the args parameter for onMapReady is structured differently and I can’t figure out how to get a reference back to MapboxView in order to call the AddMarkers method…

// Code to generate map programmatically
var mapboxView = new Mapbox.MapboxView();
mapboxView.height = 300;
 ....
mapboxView.mapReady = onMapReady(args);
function onMapReady(args) {
    args.map.addMarkers(...)   // <-- This errors

Any idea what the correct syntax in args.???.addMarkers is?


#11

Come on dude, read documentation carefully. I even gave you the exact link in my previous comment.

args.map.addMarkers(...)

#12

So, my mistake was assuming the mapReady event handler could be specified property setter-style as per the XML approach. Using addEventListener instead appears to work and yields the necessary reference for plugin methods.

For anybody else struggling to use the plugin programmatically, the example code below creates a map and adds a marker at its centre. My thanks to manojdcoder for his advice and patience with me.

var View = require("ui/core/view");
var Mapbox = require("nativescript-mapbox");

function onPageLoaded(args) {
    var page = args.object;
    var mapboxView = new Mapbox.MapboxView();    // Use the MapboxView() constructor
    mapboxView.height = 300;    // This determines the height of the map inside the layout container
    mapboxView.accessToken = "Your API token";
    mapboxView.mapStyle = "streets";    // This can be changed to select any Mapbox style
    mapboxView.latitude = 52.3602160;    // Use the latitude and longitude properties to specify the map centre
    mapboxView.longitude = 4.8891680;
    mapboxView.zoomLevel = 9.25;
    mapboxView.showUserLocation = false;
    mapboxView.addEventListener("mapReady", onMapReady, this);    // Specifies your mapReady event handler

    var stackLayout = View.getViewById(page, "map");    // Gets a reference to a {N} layout container
    stackLayout.addChild(mapboxView);    // Adds the map to the layout container
}

function onMapReady(args) {   
    args.map.addMarkers([
        {
            id: 1,
            lat: 52.3602160, 
            lng: 4.8891680, 
            title: 'Nice location', 
            subtitle: 'Really really nice location',
            icon: "res://green_marker",
            onTap: function(args) { console.log("Marker " + args.id + " tapped"); }
        }
    ]); 
}

exports.onPageLoaded = onPageLoaded;