Skip to content

Commit 38728b8

Browse files
author
Chris Vietor
committed
fix: addSource on v8-ios-runtime + support for all geojson types including FeatureCollection
1 parent a6dd1c2 commit 38728b8

File tree

2 files changed

+111
-156
lines changed

2 files changed

+111
-156
lines changed

demo/app/main-view-model.ts

+106-34
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,94 @@ export class HelloWorldModel extends Observable {
420420

421421
public doAddLayerAndSource(): void {
422422
this.mapbox
423-
.addLayer({
424-
id: 'custom-layer-1',
423+
.addSource('custom-collection-1', {
424+
type: 'geojson',
425+
url: null,
426+
data: {
427+
type: 'FeatureCollection',
428+
features: [
429+
{
430+
type: 'Feature',
431+
properties: {},
432+
geometry: {
433+
type: 'LineString',
434+
coordinates: [
435+
[4.744720458984375, 52.47357958606801],
436+
[5.108642578125, 52.24882376803033],
437+
],
438+
},
439+
},
440+
{
441+
type: 'Feature',
442+
properties: {},
443+
geometry: {
444+
type: 'Point',
445+
coordinates: [4.823684692382513, 52.3701494345567],
446+
},
447+
},
448+
{
449+
type: 'Feature',
450+
properties: {},
451+
geometry: {
452+
type: 'Point',
453+
coordinates: [4.8703765869140625, 52.3479242945069],
454+
},
455+
},
456+
{
457+
type: 'Feature',
458+
properties: {},
459+
geometry: {
460+
type: 'LineString',
461+
coordinates: [
462+
[4.7989654541015625, 52.40577019043],
463+
[4.7866058349609375, 52.36008660493161],
464+
[4.854583740234375, 52.32736657808751],
465+
[4.9376678466796875, 52.338695481504814],
466+
],
467+
},
468+
},
469+
],
470+
},
471+
})
472+
.then(() => {
473+
console.log('source with id custom-collection-1 successfully added');
474+
475+
this.mapbox
476+
.addLayer({
477+
id: 'line-layer-1',
478+
type: 'line',
479+
source: 'custom-collection-1',
480+
layout: {
481+
'line-cap': 'butt',
482+
'line-join': 'bevel',
483+
},
484+
paint: {
485+
'line-color': '#053481',
486+
'line-width': 5,
487+
'line-opacity': 0.8,
488+
'line-dash-array': [1, 1, 1, 1],
489+
},
490+
})
491+
.then(() => console.log('line-layer-1 added to source custom-collection-1'));
492+
493+
this.mapbox
494+
.addLayer({
495+
id: 'circle-layer-1',
496+
type: 'circle',
497+
source: 'custom-collection-1',
498+
paint: {
499+
'circle-radius': 2,
500+
'circle-opacity': 0.05,
501+
'circle-color': '#ed6498',
502+
'circle-stroke-width': 2,
503+
'circle-stroke-color': '#ed6498',
504+
},
505+
})
506+
.then(() => console.log('circle-layer-1 added to source custom-collection-1'));
507+
});
508+
509+
this.mapbox.addLayer({
510+
id: 'layer-with-source-object',
425511
type: 'line',
426512
source: {
427513
type: 'geojson',
@@ -431,48 +517,34 @@ export class HelloWorldModel extends Observable {
431517
geometry: {
432518
type: 'LineString',
433519
coordinates: [
434-
[4.744720458984375, 52.47357958606801],
435-
[5.108642578125, 52.24882376803033],
520+
[4.80926513671875, 52.27403984182285],
521+
[4.9383544921875, 52.30931825948968],
436522
],
437523
},
438-
},
439-
url: null,
524+
}
440525
},
441526
layout: {
442-
'line-cap': 'round',
527+
'line-cap': 'square',
443528
'line-join': 'round',
529+
'line-blur': 15
444530
},
445531
paint: {
446-
'line-color': '#053481',
447-
'line-width': 5,
448-
'line-opacity': 0.8,
449-
'line-dash-array': [1, 1, 1, 1],
450-
},
451-
})
452-
.catch(console.error);
532+
'line-color': '#5dbcd2',
533+
'line-width': 8,
534+
'line-opacity': 0.5
535+
}
536+
}).then(() => console.log('layer-with-source-object added'));
453537
}
454538

455539
public doRemoveLayerAndSource(): void {
456-
this.mapbox.removeLayer('custom-layer-1').then(
457-
() => {
458-
/*
459-
layer 'custom-layer-1' implicitly added a source under the hood,
460-
so the source id was generate as <layer-id>_source, i.e.: 'custom-layer-1_source'
461-
*/
462-
const sourceId = 'custom-layer-1_source';
463-
this.mapbox.removeSource(sourceId).then(
464-
() => {
465-
console.log('Mapbox doRemoveLayerAndSource done');
466-
},
467-
(error: string) => {
468-
console.log('mapbox doAddSource error: ' + error);
469-
}
470-
);
471-
},
472-
(error: string) => {
473-
console.log('mapbox doAddSource error: ' + error);
474-
}
475-
);
540+
Promise.all([
541+
this.mapbox.removeLayer('line-layer-1'),
542+
this.mapbox.removeLayer('circle-layer-1'),
543+
this.mapbox.removeLayer('layer-with-source-object')
544+
]).then(() => {
545+
this.mapbox.removeSource('custom-collection-1');
546+
this.mapbox.removeSource('layer-with-source-object_source');
547+
})
476548
}
477549

478550
// ===============================================================

src/mapbox.ios.ts

+5-122
Original file line numberDiff line numberDiff line change
@@ -2129,129 +2129,16 @@ export class Mapbox extends MapboxCommon implements MapboxApi {
21292129
break;
21302130

21312131
case 'geojson':
2132-
// has a source with this id already been defined? If so, then it is an error (because attempting
2133-
// to add another source with the same id will crash the app.
2134-
21352132
if (theMap.style.sourceWithIdentifier(id)) {
21362133
reject("Remove the layer with this id first with 'removeLayer': " + id);
21372134
return;
21382135
}
21392136

2140-
// under iOS we handle lines and circles differently
2141-
2142-
if (options.data.geometry.type === 'LineString') {
2143-
// after hours and hours of trial and error, I finally stumbled upon how to set things
2144-
// up so that MGLPolylineFeature.polylineWithCoordinatesCount works.
2145-
//
2146-
// Allocating an NSArray and passing it in would cause the app to crash.
2147-
// Creating a javascript array of CLLocationCoodinate2D entries would cause random
2148-
// lines to be drawn on the map.
2149-
//
2150-
// However, allocating a raw C buffer and accessing it through a reference cast to CLLocationCoordinate2D
2151-
// works (to my shock and horror).
2152-
2153-
const coordinates = options.data.geometry.coordinates;
2154-
2155-
const buffer = malloc(coordinates.length * 2 * interop.sizeof(interop.types.double));
2156-
const clCoordsArray = new interop.Reference(CLLocationCoordinate2D, buffer);
2157-
2158-
// We need to convert our coordinate array into an array of CLLocationCoodinate2D elements
2159-
// which are in lat/lng order and not lng/lat
2160-
2161-
for (let i = 0; i < coordinates.length; i++) {
2162-
const newCoord: CLLocationCoordinate2D = CLLocationCoordinate2DMake(coordinates[i][1], coordinates[i][0]);
2163-
clCoordsArray[i] = newCoord;
2164-
}
2165-
2166-
if (Trace.isEnabled()) {
2167-
CLog(CLogTypes.info, 'Mapbox:addSource(): after CLLocationCoordinate2D array before creating polyline source from clCoordsArray');
2168-
}
2169-
2170-
const polyline = MGLPolylineFeature.polylineWithCoordinatesCount(new interop.Reference(CLLocationCoordinate2D, clCoordsArray), coordinates.length);
2171-
2172-
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, polyline, null);
2173-
2174-
theMap.style.addSource(source);
2175-
2176-
// To support handling click events on lines and circles, we keep the underlying
2177-
// feature.
2178-
//
2179-
// FIXME: There should be a way to get the original feature back out from the source
2180-
// but I have not yet figured out how.
2181-
2182-
this.lines.push({
2183-
type: 'line',
2184-
id,
2185-
clCoordsArray,
2186-
numCoords: coordinates.length,
2187-
source,
2188-
});
2189-
} else if (options.data.geometry.type === 'Point') {
2190-
// FIXME: should be able to just call addSource here for type geoJson
2191-
2192-
if (Trace.isEnabled()) {
2193-
CLog(CLogTypes.info, 'Mapbox:addSource(): before addSource with options:', options);
2194-
}
2195-
2196-
const geoJSON = `{"type": "FeatureCollection", "features": [ ${JSON.stringify(options.data)}]}`;
2197-
2198-
// this would otherwise crash the app
2199-
2200-
if (theMap.style.sourceWithIdentifier(id)) {
2201-
reject("Remove the layer with this id first with 'removeLayer': " + id);
2202-
return;
2203-
}
2204-
2205-
if (Trace.isEnabled()) {
2206-
CLog(CLogTypes.info, 'Mapbox:addSource(): after checking for existing style');
2207-
}
2208-
2209-
const geoDataStr = NSString.stringWithString(geoJSON);
2210-
2211-
if (Trace.isEnabled()) {
2212-
CLog(CLogTypes.info, 'Mapbox:addSource(): after string');
2213-
}
2214-
2215-
const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
2216-
2217-
if (Trace.isEnabled()) {
2218-
CLog(CLogTypes.info, 'Mapbox:addSource(): after encoding');
2219-
}
2220-
2221-
const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
2222-
2223-
if (Trace.isEnabled()) {
2224-
CLog(CLogTypes.info, 'Mapbox:addSource(): before alloc');
2225-
}
2226-
2227-
const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
2228-
2229-
if (Trace.isEnabled()) {
2230-
CLog(CLogTypes.info, "Mapbox:addSource(): before shape with id '" + id + "'");
2231-
}
2232-
2233-
const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
2234-
2235-
if (Trace.isEnabled()) {
2236-
CLog(CLogTypes.info, "Mapbox:addSource(): after shape before second alloc with id '" + id + "' and shape '" + shape + "'");
2237-
}
2238-
2239-
const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, shape, null);
2240-
2241-
if (Trace.isEnabled()) {
2242-
CLog(CLogTypes.info, 'Mapbox:addSource(): before addSource');
2243-
}
2244-
2245-
theMap.style.addSource(source);
2246-
2247-
// probably a circle
2248-
2249-
this.circles.push({
2250-
type: 'line',
2251-
id,
2252-
center: options.data.geometry.coordinates,
2253-
});
2254-
}
2137+
const content: NSString = NSString.stringWithString(JSON.stringify(options.data));
2138+
const nsData: NSData = content.dataUsingEncoding(NSUTF8StringEncoding);
2139+
const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
2140+
2141+
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, null);
22552142

22562143
break;
22572144

@@ -2719,10 +2606,6 @@ export class Mapbox extends MapboxCommon implements MapboxApi {
27192606
reject('Non circle style passed to addCircleLayer()');
27202607
}
27212608

2722-
if (typeof style.source != 'undefined') {
2723-
reject('Missing source.');
2724-
}
2725-
27262609
// the source may be of type geojson, vector, or it may be the id of a source added by addSource().
27272610

27282611
let sourceId = null;

0 commit comments

Comments
 (0)