Skip to content

Commit

Permalink
add onPress for polygons and polylines on iOS and Android
Browse files Browse the repository at this point in the history
  • Loading branch information
frankrowe authored and Exilz committed Dec 9, 2016
1 parent 1e6520b commit 285bc66
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public Object getFeature() {
@Override
public void addToMap(GoogleMap map) {
polygon = map.addPolygon(getPolygonOptions());
polygon.setClickable(true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;

import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;

public class AirMapPolygonManager extends ViewGroupManager<AirMapPolygon> {
private final DisplayMetrics metrics;

Expand Down Expand Up @@ -67,4 +72,13 @@ public void setGeodesic(AirMapPolygon view, boolean geodesic) {
public void setZIndex(AirMapPolygon view, float zIndex) {
view.setZIndex(zIndex);
}

@Override
@Nullable
public Map getExportedCustomDirectEventTypeConstants() {
Map map = MapBuilder.of(
"onPress", MapBuilder.of("registrationName", "onPress")
);
return map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public Object getFeature() {
@Override
public void addToMap(GoogleMap map) {
polyline = map.addPolyline(getPolylineOptions());
polyline.setClickable(true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;

import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;

public class AirMapPolylineManager extends ViewGroupManager<AirMapPolyline> {
private final DisplayMetrics metrics;

Expand Down Expand Up @@ -62,4 +67,13 @@ public void setGeodesic(AirMapPolyline view, boolean geodesic) {
public void setZIndex(AirMapPolyline view, float zIndex) {
view.setZIndex(zIndex);
}

@Override
@Nullable
public Map getExportedCustomDirectEventTypeConstants() {
Map map = MapBuilder.of(
"onPress", MapBuilder.of("registrationName", "onPress")
);
return map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.Polygon;
import com.google.android.gms.maps.model.Polyline;

import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -72,6 +74,8 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter,

private final List<AirMapFeature> features = new ArrayList<>();
private final Map<Marker, AirMapMarker> markerMap = new HashMap<>();
private final Map<Polyline, AirMapPolyline> polylineMap = new HashMap<>();
private final Map<Polygon, AirMapPolygon> polygonMap = new HashMap<>();
private final ScaleGestureDetector scaleDetector;
private final GestureDetectorCompat gestureDetector;
private final AirMapManager manager;
Expand Down Expand Up @@ -165,6 +169,26 @@ public boolean onMarkerClick(Marker marker) {
}
});

map.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() {
@Override
public void onPolygonClick(Polygon polygon) {
WritableMap event;
event = makeClickEventData(polygon.getPoints().get(0));
event.putString("action", "polygon-press");
manager.pushEvent(polygonMap.get(polygon), "onPress", event);
}
});

map.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
@Override
public void onPolylineClick(Polyline polyline) {
WritableMap event;
event = makeClickEventData(polyline.getPoints().get(0));
event.putString("action", "polyline-press");
manager.pushEvent(polylineMap.get(polyline), "onPress", event);
}
});

map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
Expand Down Expand Up @@ -381,10 +405,14 @@ public void addFeature(View child, int index) {
AirMapPolyline polylineView = (AirMapPolyline) child;
polylineView.addToMap(map);
features.add(index, polylineView);
Polyline polyline = (Polyline) polylineView.getFeature();
polylineMap.put(polyline, polylineView);
} else if (child instanceof AirMapPolygon) {
AirMapPolygon polygonView = (AirMapPolygon) child;
polygonView.addToMap(map);
features.add(index, polygonView);
Polygon polygon = (Polygon) polygonView.getFeature();
polygonMap.put(polygon, polygonView);
} else if (child instanceof AirMapCircle) {
AirMapCircle circleView = (AirMapCircle) child;
circleView.addToMap(map);
Expand Down
119 changes: 111 additions & 8 deletions ios/AirMaps/AIRMapManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ - (void)takeMapSnapshot:(AIRMap *)mapView
[pin.image drawAtPoint:point];
}
}

for (id <AIRMapSnapshot> overlay in mapView.overlays) {
if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) {
[overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
Expand Down Expand Up @@ -346,21 +346,75 @@ - (void)takeMapSnapshot:(AIRMap *)mapView

#pragma mark Gesture Recognizer Handlers

#define MAX_DISTANCE_PX 10.0f
- (void)handleMapTap:(UITapGestureRecognizer *)recognizer {
AIRMap *map = (AIRMap *)recognizer.view;
if (!map.onPress) return;

CGPoint touchPoint = [recognizer locationInView:map];
CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
CGPoint tapPoint = [recognizer locationInView:map];
CLLocationCoordinate2D tapCoordinate = [map convertPoint:tapPoint toCoordinateFromView:map];
MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoordinate);
CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);

double maxMeters = [self metersFromPixel:MAX_DISTANCE_PX atPoint:tapPoint forMap:map];
float nearestDistance = MAXFLOAT;
AIRMapPolyline *nearestPolyline = nil;

for (id<MKOverlay> overlay in map.overlays) {
if([overlay isKindOfClass:[AIRMapPolygon class]]){
AIRMapPolygon *polygon = (AIRMapPolygon*) overlay;
if (polygon.onPress) {
CGMutablePathRef mpr = CGPathCreateMutable();

for(int i = 0; i < polygon.coordinates.count; i++) {
AIRMapCoordinate *c = polygon.coordinates[i];
MKMapPoint mp = MKMapPointForCoordinate(c.coordinate);
if (i == 0) {
CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
} else {
CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
}
}

if (CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE)) {
id event = @{
@"action": @"polygon-press",
};
polygon.onPress(event);
}

CGPathRelease(mpr);
}
}

if([overlay isKindOfClass:[AIRMapPolyline class]]){
AIRMapPolyline *polyline = (AIRMapPolyline*) overlay;
if (polyline.onPress) {
float distance = [self distanceOfPoint:MKMapPointForCoordinate(tapCoordinate)
toPoly:overlay];
if (distance < nearestDistance) {
nearestDistance = distance;
nearestPolyline = overlay;
}
}
}
}

if (nearestDistance <= maxMeters) {
id event = @{
@"action": @"polyline-press",
};
nearestPolyline.onPress(event);
}

if (!map.onPress) return;
map.onPress(@{
@"coordinate": @{
@"latitude": @(coord.latitude),
@"longitude": @(coord.longitude),
@"latitude": @(tapCoordinate.latitude),
@"longitude": @(tapCoordinate.longitude),
},
@"position": @{
@"x": @(touchPoint.x),
@"y": @(touchPoint.y),
@"x": @(tapPoint.x),
@"y": @(tapPoint.y),
},
});

Expand Down Expand Up @@ -647,4 +701,53 @@ - (void)_emitRegionChangeEvent:(AIRMap *)mapView continuous:(BOOL)continuous
}
}

/** Returns the distance of |pt| to |poly| in meters
*
*
*/
- (double)distanceOfPoint:(MKMapPoint)pt toPoly:(AIRMapPolyline *)poly
{
double distance = MAXFLOAT;
for (int n = 0; n < poly.coordinates.count - 1; n++) {

MKMapPoint ptA = MKMapPointForCoordinate(poly.coordinates[n].coordinate);
MKMapPoint ptB = MKMapPointForCoordinate(poly.coordinates[n + 1].coordinate);

double xDelta = ptB.x - ptA.x;
double yDelta = ptB.y - ptA.y;

if (xDelta == 0.0 && yDelta == 0.0) {
continue;
}

double u = ((pt.x - ptA.x) * xDelta + (pt.y - ptA.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta);
MKMapPoint ptClosest;
if (u < 0.0) {
ptClosest = ptA;
}
else if (u > 1.0) {
ptClosest = ptB;
}
else {
ptClosest = MKMapPointMake(ptA.x + u * xDelta, ptA.y + u * yDelta);
}

distance = MIN(distance, MKMetersBetweenMapPoints(ptClosest, pt));
}

return distance;
}


/** Converts |px| to meters at location |pt| */
- (double)metersFromPixel:(NSUInteger)px atPoint:(CGPoint)pt forMap:(AIRMap *)mapView
{
CGPoint ptB = CGPointMake(pt.x + px, pt.y);

CLLocationCoordinate2D coordA = [mapView convertPoint:pt toCoordinateFromView:mapView];
CLLocationCoordinate2D coordB = [mapView convertPoint:ptB toCoordinateFromView:mapView];

return MKMetersBetweenMapPoints(MKMapPointForCoordinate(coordA), MKMapPointForCoordinate(coordB));
}

@end
1 change: 1 addition & 0 deletions ios/AirMaps/AIRMapPolygon.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
@property (nonatomic, assign) CGLineJoin lineJoin;
@property (nonatomic, assign) CGFloat lineDashPhase;
@property (nonatomic, strong) NSArray <NSNumber *> *lineDashPattern;
@property (nonatomic, copy) RCTBubblingEventBlock onPress;

#pragma mark MKOverlay protocol

Expand Down
5 changes: 1 addition & 4 deletions ios/AirMaps/AIRMapPolygonManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(miterLimit, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(lineDashPhase, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(lineDashPattern, NSArray)
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)

// NOTE(lmr):
// for now, onPress events for overlays will be left unimplemented. Seems it is possible with some work, but
// it is difficult to achieve in both ios and android so I decided to leave it out.
//RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)

@end
1 change: 1 addition & 0 deletions ios/AirMaps/AIRMapPolyline.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
@property (nonatomic, assign) CGLineJoin lineJoin;
@property (nonatomic, assign) CGFloat lineDashPhase;
@property (nonatomic, strong) NSArray <NSNumber *> *lineDashPattern;
@property (nonatomic, copy) RCTBubblingEventBlock onPress;

#pragma mark MKOverlay protocol

Expand Down
6 changes: 1 addition & 5 deletions ios/AirMaps/AIRMapPolylineManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(miterLimit, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(lineDashPhase, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(lineDashPattern, NSArray)

// NOTE(lmr):
// for now, onPress events for overlays will be left unimplemented. Seems it is possible with some work, but
// it is difficult to achieve in both ios and android so I decided to leave it out.
//RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)

@end

0 comments on commit 285bc66

Please sign in to comment.