Skip to content

Commit c85769e

Browse files
therealgillesgilbox
authored andcommitted
Add support for polygon holes for Apple Maps and Google Maps on iOS (react-native-maps#801)
* Add support for polygon holes for Apple Maps and Google Maps on iOS * Add PropTypes for polygon holes * Add support for polygon holes in Polygon Creator example
1 parent d945be7 commit c85769e

9 files changed

+124
-6
lines changed

components/MapPolygon.js

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ const propTypes = {
2121
longitude: PropTypes.number.isRequired,
2222
})),
2323

24+
/**
25+
* An array of array of coordinates to describe the polygon holes
26+
*/
27+
holes: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.shape({
28+
/**
29+
* Latitude/Longitude coordinates
30+
*/
31+
latitude: PropTypes.number.isRequired,
32+
longitude: PropTypes.number.isRequired,
33+
}))),
34+
2435
/**
2536
* Callback that is called when the user presses on the polygon
2637
*/

example/examples/PolygonCreator.js

+60-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class PolygonCreator extends React.Component {
3131
},
3232
polygons: [],
3333
editing: null,
34+
creatingHole: false,
3435
};
3536
}
3637

@@ -39,19 +40,49 @@ class PolygonCreator extends React.Component {
3940
this.setState({
4041
polygons: [...polygons, editing],
4142
editing: null,
43+
creatingHole: false,
4244
});
4345
}
4446

47+
createHole() {
48+
const { editing, creatingHole } = this.state;
49+
if (!creatingHole) {
50+
this.setState({
51+
creatingHole: true,
52+
editing: {
53+
...editing,
54+
holes: [
55+
...editing.holes,
56+
[],
57+
],
58+
},
59+
});
60+
} else {
61+
const holes = [...editing.holes];
62+
if (holes[holes.length - 1].length === 0) {
63+
holes.pop();
64+
this.setState({
65+
editing: {
66+
...editing,
67+
holes,
68+
},
69+
});
70+
}
71+
this.setState({ creatingHole: false });
72+
}
73+
}
74+
4575
onPress(e) {
46-
const { editing } = this.state;
76+
const { editing, creatingHole } = this.state;
4777
if (!editing) {
4878
this.setState({
4979
editing: {
5080
id: id++,
5181
coordinates: [e.nativeEvent.coordinate],
82+
holes: [],
5283
},
5384
});
54-
} else {
85+
} else if (!creatingHole) {
5586
this.setState({
5687
editing: {
5788
...editing,
@@ -61,6 +92,22 @@ class PolygonCreator extends React.Component {
6192
],
6293
},
6394
});
95+
} else {
96+
const holes = [...editing.holes];
97+
holes[holes.length - 1] = [
98+
...holes[holes.length - 1],
99+
e.nativeEvent.coordinate,
100+
];
101+
this.setState({
102+
editing: {
103+
...editing,
104+
id: id++, // keep incrementing id to trigger display refresh
105+
coordinates: [
106+
...editing.coordinates,
107+
],
108+
holes,
109+
},
110+
});
64111
}
65112
}
66113

@@ -88,21 +135,32 @@ class PolygonCreator extends React.Component {
88135
<MapView.Polygon
89136
key={polygon.id}
90137
coordinates={polygon.coordinates}
138+
holes={polygon.holes}
91139
strokeColor="#F00"
92140
fillColor="rgba(255,0,0,0.5)"
93141
strokeWidth={1}
94142
/>
95143
))}
96144
{this.state.editing && (
97145
<MapView.Polygon
146+
key={this.state.editing.id}
98147
coordinates={this.state.editing.coordinates}
148+
holes={this.state.editing.holes}
99149
strokeColor="#000"
100150
fillColor="rgba(255,0,0,0.5)"
101151
strokeWidth={1}
102152
/>
103153
)}
104154
</MapView>
105155
<View style={styles.buttonContainer}>
156+
{this.state.editing && (
157+
<TouchableOpacity
158+
onPress={() => this.createHole()}
159+
style={[styles.bubble, styles.button]}
160+
>
161+
<Text>{this.state.creatingHole ? 'Finish Hole' : 'Create Hole'}</Text>
162+
</TouchableOpacity>
163+
)}
106164
{this.state.editing && (
107165
<TouchableOpacity
108166
onPress={() => this.finish()}

ios/AirGoogleMaps/AIRGoogleMapPolygon.h

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
@property (nonatomic, strong) GMSPolygon *polygon;
1313
@property (nonatomic, strong) NSArray<AIRMapCoordinate *> *coordinates;
14+
@property (nonatomic, strong) NSArray<NSArray<AIRMapCoordinate *> *> *holes;
1415

1516
@property (nonatomic, assign) UIColor *fillColor;
1617
@property (nonatomic, assign) double strokeWidth;

ios/AirGoogleMaps/AIRGoogleMapPolygon.m

+21
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ - (void)setCoordinates:(NSArray<AIRMapCoordinate *> *)coordinates
3131
_polygon.path = path;
3232
}
3333

34+
- (void)setHoles:(NSArray<NSArray<AIRMapCoordinate *> *> *)holes
35+
{
36+
_holes = holes;
37+
38+
if (holes.count)
39+
{
40+
NSMutableArray<GMSMutablePath *> *interiorPolygons = [NSMutableArray array];
41+
for(int h = 0; h < holes.count; h++)
42+
{
43+
GMSMutablePath *path = [GMSMutablePath path];
44+
for(int i = 0; i < holes[h].count; i++)
45+
{
46+
[path addCoordinate:holes[h][i].coordinate];
47+
}
48+
[interiorPolygons addObject:path];
49+
}
50+
51+
_polygon.holes = interiorPolygons;
52+
}
53+
}
54+
3455
-(void)setFillColor:(UIColor *)fillColor
3556
{
3657
_fillColor = fillColor;

ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ - (UIView *)view
2929
}
3030

3131
RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray)
32+
RCT_EXPORT_VIEW_PROPERTY(holes, AIRMapCoordinateArrayArray)
3233
RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor)
3334
RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double)
3435
RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor)

ios/AirMaps/AIRMapPolygon.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
@property (nonatomic, strong) MKPolygon *polygon;
2424
@property (nonatomic, strong) MKPolygonRenderer *renderer;
25+
@property (nonatomic, strong) NSArray<MKPolygon *> *interiorPolygons;
2526

2627
@property (nonatomic, strong) NSArray<AIRMapCoordinate *> *coordinates;
28+
@property (nonatomic, strong) NSArray<NSArray<AIRMapCoordinate *> *> *holes;
2729
@property (nonatomic, strong) UIColor *fillColor;
2830
@property (nonatomic, strong) UIColor *strokeColor;
2931
@property (nonatomic, assign) CGFloat strokeWidth;
@@ -41,4 +43,4 @@
4143
- (BOOL)intersectsMapRect:(MKMapRect)mapRect;
4244
- (BOOL)canReplaceMapContent;
4345

44-
@end
46+
@end

ios/AirMaps/AIRMapPolygon.m

+20-2
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,31 @@ - (void)setCoordinates:(NSArray<AIRMapCoordinate *> *)coordinates {
5858
{
5959
coords[i] = coordinates[i].coordinate;
6060
}
61-
self.polygon = [MKPolygon polygonWithCoordinates:coords count:coordinates.count];
61+
self.polygon = [MKPolygon polygonWithCoordinates:coords count:coordinates.count interiorPolygons:_interiorPolygons];
6262
// TODO: we could lazy-initialize the polygon, since we don't need it until the
6363
// polygon is in view.
6464
self.renderer = [[MKPolygonRenderer alloc] initWithPolygon:self.polygon];
6565
[self update];
6666
}
6767

68+
- (void)setHoles:(NSArray<NSArray<AIRMapCoordinate *> *> *)holes {
69+
_holes = holes;
70+
if (holes.count)
71+
{
72+
NSMutableArray<MKPolygon *> *polygons = [NSMutableArray array];
73+
for(int h = 0; h < holes.count; h++)
74+
{
75+
CLLocationCoordinate2D coords[holes[h].count];
76+
for(int i = 0; i < holes[h].count; i++)
77+
{
78+
coords[i] = holes[h][i].coordinate;
79+
}
80+
[polygons addObject:[MKPolygon polygonWithCoordinates:coords count:holes[h].count]];
81+
}
82+
_interiorPolygons = polygons;
83+
}
84+
}
85+
6886
- (void) update
6987
{
7088
if (!_renderer) return;
@@ -157,4 +175,4 @@ - (BOOL)canReplaceMapContent
157175

158176

159177

160-
@end
178+
@end

ios/AirMaps/AIRMapPolygonManager.m

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ - (UIView *)view
3434
}
3535

3636
RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray)
37+
RCT_EXPORT_VIEW_PROPERTY(holes, AIRMapCoordinateArrayArray)
3738
RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor)
3839
RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor)
3940
RCT_EXPORT_VIEW_PROPERTY(strokeWidth, CGFloat)

ios/AirMaps/RCTConvert+MoreMapKit.m

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,9 @@ + (AIRMapCoordinate *)AIRMapCoordinate:(id)json
2424

2525
RCT_ARRAY_CONVERTER(AIRMapCoordinate)
2626

27-
@end
27+
+ (NSArray<NSArray<AIRMapCoordinate *> *> *)AIRMapCoordinateArrayArray:(id)json
28+
{
29+
return RCTConvertArrayValue(@selector(AIRMapCoordinateArray:), json);
30+
}
31+
32+
@end

0 commit comments

Comments
 (0)