Skip to content

Commit

Permalink
Support for Marker Image URLs #20
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyVerbruggen committed Nov 16, 2016
1 parent 01a8cf7 commit 24c149c
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 48 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ Check out the usage details on the functions below.
title: 'Nice location', // recommended to pass in
subtitle: 'Really really nice location', // one line is available on iOS, multiple on Android
icon: 'res://cool_marker', // use either this preferred way (to grab a density-independent marker from app resources), or:
icon: 'http(s)://my-remote-image', // an image from the interwebs, or:
iconPath: 'res/markers/green_pin_marker.png', // anywhere in your app folder
onTap: function(marker) { console.log("This marker was tapped"); },
onCalloutTap: function(marker) { console.log("The callout of this marker was tapped"); }
Expand Down Expand Up @@ -231,6 +232,7 @@ You can update the map style after you've loaded it. How neat is that!?
title: 'One-line title here', // no popup unless set
subtitle: 'Infamous subtitle!',
icon: 'res://cool_marker', // preferred way, otherwise use:
icon: 'http(s)://website/coolimage.png', // from the internet, or:
iconPath: 'res/markers/home_marker.png',
onTap: onTap,
onCalloutTap: onCalloutTap
Expand Down
110 changes: 80 additions & 30 deletions mapbox.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ var application = require("application");
var frame = require("ui/frame");
var fs = require("file-system");
var Color = require("color").Color;
var http = require("http");
var mapbox = require("./mapbox-common");
mapbox._markers = [];
mapbox._polylines = [];
mapbox._markerIconDownloadCache = [];
var ACCESS_FINE_LOCATION_PERMISSION_REQUEST_CODE = 111;

mapbox.locationServices = null;
Expand Down Expand Up @@ -374,6 +376,46 @@ mapbox.addMarkers = function (markers, nativeMap) {
});
};

function downloadImage(marker) {
return new Promise(function (resolve, reject) {
// to cache..
if (mapbox._markerIconDownloadCache[marker.icon]) {
marker.iconDownloaded = mapbox._markerIconDownloadCache[marker.icon];
resolve(marker);
return;
}
// ..or not to cache
http.getImage(marker.icon).then(
function (output) {
marker.iconDownloaded = output.android;
mapbox._markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
resolve(marker);
}, function (e) {
console.log("Download failed from " + marker.icon + " with error: " + e);
resolve(marker);
});
});
}

function downloadMarkerImages(markers) {
var iterations = [];
var result = [];
for (var i = 0; i < markers.length; i++) {
var marker = markers[i];
if (marker.icon && marker.icon.startsWith("http")) {
var p = downloadImage(marker).then(function(mark) {
result.push(mark);
});
iterations.push(p);
} else {
result.push(marker);
}
}
return Promise.all(iterations).then(function(output) {
return result;
});
}

mapbox._addMarkers = function(markers, nativeMap) {
if (!markers) {
console.log("No markers passed");
Expand Down Expand Up @@ -410,40 +452,48 @@ mapbox._addMarkers = function(markers, nativeMap) {
);

var iconFactory = com.mapbox.mapboxsdk.annotations.IconFactory.getInstance(application.android.context);
for (var m in markers) {
var marker = markers[m];
mapbox._markers.push(marker);
var markerOptions = new com.mapbox.mapboxsdk.annotations.MarkerOptions();
markerOptions.setTitle(marker.title);
markerOptions.setSnippet(marker.subtitle);
markerOptions.setPosition(new com.mapbox.mapboxsdk.geometry.LatLng(marker.lat, marker.lng));
if (marker.icon) {
if (marker.icon.startsWith("res://")) {
var resourcename = marker.icon.substring(6);
var res = utils.ad.getApplicationContext().getResources();
var identifier = res.getIdentifier(resourcename, "drawable", utils.ad.getApplication().getPackageName());

if (identifier === 0) {
console.log("No icon found for this device desity for icon " + marker.icon + ", using default");

// if any markers need to be downloaded from the web they need to be available synchronously, so fetch them first before looping
downloadMarkerImages(markers).then(function(updatedMarkers) {
for (var m in updatedMarkers) {
var marker = updatedMarkers[m];
mapbox._markers.push(marker);
var markerOptions = new com.mapbox.mapboxsdk.annotations.MarkerOptions();
markerOptions.setTitle(marker.title);
markerOptions.setSnippet(marker.subtitle);
markerOptions.setPosition(new com.mapbox.mapboxsdk.geometry.LatLng(marker.lat, marker.lng));
if (marker.icon) {
// for markers from url see UrlMarker in https://github.com/mapbox/mapbox-gl-native/issues/5370
if (marker.icon.startsWith("res://")) {
var resourcename = marker.icon.substring(6);
var res = utils.ad.getApplicationContext().getResources();
var identifier = res.getIdentifier(resourcename, "drawable", utils.ad.getApplication().getPackageName());
if (identifier === 0) {
console.log("No icon found for this device desity for icon " + marker.icon + ", using default");
} else {
var iconDrawable = android.support.v4.content.ContextCompat.getDrawable(application.android.context, identifier);
markerOptions.setIcon(iconFactory.fromDrawable(iconDrawable));
}
} else if (marker.icon.startsWith("http")) {
if (marker.iconDownloaded !== null) {
markerOptions.setIcon(iconFactory.fromBitmap(marker.iconDownloaded));
}
} else {
var iconDrawable = android.support.v4.content.ContextCompat.getDrawable(application.android.context, identifier);
markerOptions.setIcon(iconFactory.fromDrawable(iconDrawable));
console.log("Please use res://resourcename, http(s)://imageurl or iconPath to use a local path");
}
} else if (marker.iconPath) {
var iconFullPath = fs.knownFolders.currentApp().path + "/" + marker.iconPath;
// if the file doesn't exist the app will crash, so checking it
if (fs.File.exists(iconFullPath)) {
// could set width, height, retina, see https://github.com/Telerik-Verified-Plugins/Mapbox/pull/42/files?diff=unified&short_path=1c65267, but that's what the marker.icon param is for..
markerOptions.setIcon(iconFactory.fromPath(iconFullPath));
} else {
console.log("Marker icon not found, using the default instead. Requested full path: " + iconFullPath);
}
} else {
console.log("Please use res://resourcename, or iconPath to use a local path");
}
} else if (marker.iconPath) {
var iconFullPath = fs.knownFolders.currentApp().path + "/" + marker.iconPath;
// if the file doesn't exist the app will crash, so checking it
if (fs.File.exists(iconFullPath)) {
// could set width, height, retina, see https://github.com/Telerik-Verified-Plugins/Mapbox/pull/42/files?diff=unified&short_path=1c65267, but that's what the marker.icon param is for..
markerOptions.setIcon(iconFactory.fromPath(iconFullPath));
} else {
console.log("Marker icon not found, using the default instead. Requested full path: " + iconFullPath);
}
marker.android = theMap.mapboxMap.addMarker(markerOptions);
}
marker.android = theMap.mapboxMap.addMarker(markerOptions);
}
});
};

mapbox.setCenter = function (arg, nativeMap) {
Expand Down
89 changes: 72 additions & 17 deletions mapbox.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ var mapbox = require("./mapbox-common");
var fs = require("file-system");
var imgSrc = require("image-source");
var utils = require("utils/utils");
var http = require("http");

mapbox._markers = [];
mapbox._markerIconDownloadCache = [];

(function() {
// need to kick this off otherwise offline stuff won't work without first showing a map
Expand Down Expand Up @@ -239,6 +242,46 @@ mapbox.addMarkers = function (markers, nativeMap) {
});
};

function downloadImage(marker) {
return new Promise(function (resolve, reject) {
// to cache..
if (mapbox._markerIconDownloadCache[marker.icon]) {
marker.iconDownloaded = mapbox._markerIconDownloadCache[marker.icon];
resolve(marker);
return;
}
// ..or not to cache
http.getImage(marker.icon).then(
function (output) {
marker.iconDownloaded = output.ios;
mapbox._markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
resolve(marker);
}, function (e) {
console.log("Download failed from " + marker.icon + " with error: " + e);
resolve(marker);
});
});
}

function downloadMarkerImages(markers) {
var iterations = [];
var result = [];
for (var i = 0; i < markers.length; i++) {
var marker = markers[i];
if (marker.icon && marker.icon.startsWith("http")) {
var p = downloadImage(marker).then(function(mark) {
result.push(mark);
});
iterations.push(p);
} else {
result.push(marker);
}
}
return Promise.all(iterations).then(function(output) {
return result;
});
}

mapbox._addMarkers = function(markers, nativeMap) {
if (!markers) {
console.log("No markers passed");
Expand All @@ -249,19 +292,22 @@ mapbox._addMarkers = function(markers, nativeMap) {
return;
}
var theMap = nativeMap || mapbox.mapView;
for (var m in markers) {
var marker = markers[m];
var lat = marker.lat;
var lng = marker.lng;
var point = MGLPointAnnotation.new();
point.coordinate = CLLocationCoordinate2DMake(lat, lng);
point.title = marker.title;
point.subtitle = marker.subtitle;
// needs to be done before adding to the map, otherwise the delegate method 'mapViewImageForAnnotation' can't use it
mapbox._markers.push(marker);
theMap.addAnnotation(point);
marker.ios = point;
}

downloadMarkerImages(markers).then(function(updatedMarkers) {
for (var m in updatedMarkers) {
var marker = updatedMarkers[m];
var lat = marker.lat;
var lng = marker.lng;
var point = MGLPointAnnotation.new();
point.coordinate = CLLocationCoordinate2DMake(lat, lng);
point.title = marker.title;
point.subtitle = marker.subtitle;
// needs to be done before adding to the map, otherwise the delegate method 'mapViewImageForAnnotation' can't use it
mapbox._markers.push(marker);
theMap.addAnnotation(point);
marker.ios = point;
}
});
};

mapbox.setCenter = function (arg, nativeMap) {
Expand Down Expand Up @@ -763,10 +809,19 @@ var MGLMapViewDelegateImpl = (function (_super) {
}

if (cachedMarker.icon) {
var resourcename = cachedMarker.icon.substring(6);
var imageSource = imgSrc.fromResource(resourcename);
cachedMarker.reuseIdentifier = cachedMarker.icon;
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
if (cachedMarker.icon.startsWith("res://")) {
var resourcename = cachedMarker.icon.substring("res://".length);
var imageSource = imgSrc.fromResource(resourcename);
cachedMarker.reuseIdentifier = cachedMarker.icon;
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
} else if (cachedMarker.icon.startsWith("http")) {
if (cachedMarker.iconDownloaded !== null) {
cachedMarker.reuseIdentifier = cachedMarker.icon;
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(cachedMarker.iconDownloaded, cachedMarker.reuseIdentifier);
}
} else {
console.log("Please use res://resourcename, http(s)://imageurl or iconPath to use a local path");
}
} else if (cachedMarker.iconPath) {
var appPath = fs.knownFolders.currentApp().path;
var iconFullPath = appPath + "/" + cachedMarker.iconPath;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nativescript-mapbox",
"version": "2.2.4",
"version": "2.3.0",
"description": "Native Maps, by Mapbox.",
"main": "mapbox.js",
"typings": "mapbox.d.ts",
Expand Down

0 comments on commit 24c149c

Please sign in to comment.