@lugg/maps 1.0.0-beta.0 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +74 -0
- package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +38 -0
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +0 -11
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +73 -51
- package/android/src/main/java/com/luggmaps/LuggPackage.kt +8 -1
- package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +181 -5
- package/ios/LuggCalloutView.h +23 -0
- package/ios/LuggCalloutView.mm +145 -0
- package/ios/LuggMarkerView.h +2 -0
- package/ios/LuggMarkerView.mm +17 -2
- package/ios/core/AppleMapProvider.mm +211 -24
- package/ios/core/GoogleMapProvider.mm +125 -5
- package/ios/core/LuggAnnotationView.h +12 -0
- package/ios/core/LuggAnnotationView.mm +55 -0
- package/lib/module/MapProvider.web.js +3 -1
- package/lib/module/MapProvider.web.js.map +1 -1
- package/lib/module/MapView.web.js +15 -2
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/components/Marker.js +21 -4
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +86 -22
- package/lib/module/components/Marker.web.js.map +1 -1
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/MapProvider.web.d.ts +6 -0
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts.map +1 -1
- package/lib/typescript/src/components/GeoJson.types.d.ts +11 -1
- package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.d.ts +1 -1
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.types.d.ts +27 -1
- package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts +1 -1
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.web.d.ts +1 -1
- package/lib/typescript/src/components/index.web.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +13 -0
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +2 -2
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/MapProvider.web.tsx +11 -1
- package/src/MapView.web.tsx +26 -2
- package/src/components/GeoJson.types.ts +12 -1
- package/src/components/Marker.tsx +29 -1
- package/src/components/Marker.types.ts +28 -1
- package/src/components/Marker.web.tsx +113 -23
- package/src/components/index.ts +1 -0
- package/src/components/index.web.ts +1 -1
- package/src/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/src/index.ts +2 -0
- package/src/index.web.ts +2 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#import <React/RCTViewComponentView.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
@class LuggCalloutView;
|
|
7
|
+
|
|
8
|
+
@protocol LuggCalloutViewDelegate <NSObject>
|
|
9
|
+
@optional
|
|
10
|
+
- (void)calloutViewDidUpdate:(LuggCalloutView *)calloutView;
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@interface LuggCalloutView : RCTViewComponentView
|
|
14
|
+
|
|
15
|
+
@property(nonatomic, readonly) BOOL bubbled;
|
|
16
|
+
@property(nonatomic, readonly) CGPoint anchor;
|
|
17
|
+
@property(nonatomic, readonly) BOOL hasCustomContent;
|
|
18
|
+
@property(nonatomic, readonly) UIView *contentView;
|
|
19
|
+
@property(nonatomic, weak, nullable) id<LuggCalloutViewDelegate> delegate;
|
|
20
|
+
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#import "LuggCalloutView.h"
|
|
2
|
+
|
|
3
|
+
#import <react/renderer/components/RNMapsSpec/ComponentDescriptors.h>
|
|
4
|
+
#import <react/renderer/components/RNMapsSpec/Props.h>
|
|
5
|
+
#import <react/renderer/components/RNMapsSpec/RCTComponentViewHelpers.h>
|
|
6
|
+
|
|
7
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
8
|
+
|
|
9
|
+
using namespace facebook::react;
|
|
10
|
+
|
|
11
|
+
@interface LuggCalloutContentView : UIView
|
|
12
|
+
- (void)updateContentSize;
|
|
13
|
+
@end
|
|
14
|
+
|
|
15
|
+
@implementation LuggCalloutContentView
|
|
16
|
+
|
|
17
|
+
- (CGSize)intrinsicContentSize {
|
|
18
|
+
CGFloat width = 0;
|
|
19
|
+
CGFloat height = 0;
|
|
20
|
+
for (UIView *subview in self.subviews) {
|
|
21
|
+
width = MAX(width, CGRectGetMaxX(subview.frame));
|
|
22
|
+
height = MAX(height, CGRectGetMaxY(subview.frame));
|
|
23
|
+
}
|
|
24
|
+
if (width > 0 && height > 0) {
|
|
25
|
+
return CGSizeMake(width, height);
|
|
26
|
+
}
|
|
27
|
+
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (void)updateContentSize {
|
|
31
|
+
CGSize size = [self intrinsicContentSize];
|
|
32
|
+
if (size.width > 0 && size.height > 0) {
|
|
33
|
+
self.frame = CGRectMake(0, 0, size.width, size.height);
|
|
34
|
+
}
|
|
35
|
+
[self invalidateIntrinsicContentSize];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@end
|
|
39
|
+
|
|
40
|
+
@interface LuggCalloutView () <RCTLuggCalloutViewViewProtocol>
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
@implementation LuggCalloutView {
|
|
44
|
+
LuggCalloutContentView *_contentView;
|
|
45
|
+
BOOL _bubbled;
|
|
46
|
+
CGPoint _anchor;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
50
|
+
return concreteComponentDescriptorProvider<
|
|
51
|
+
LuggCalloutViewComponentDescriptor>();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
55
|
+
if (self = [super initWithFrame:frame]) {
|
|
56
|
+
static const auto defaultProps =
|
|
57
|
+
std::make_shared<const LuggCalloutViewProps>();
|
|
58
|
+
_props = defaultProps;
|
|
59
|
+
|
|
60
|
+
_bubbled = YES;
|
|
61
|
+
_anchor = CGPointMake(0.5, 1.0);
|
|
62
|
+
_contentView = [[LuggCalloutContentView alloc] init];
|
|
63
|
+
_contentView.backgroundColor = [UIColor clearColor];
|
|
64
|
+
|
|
65
|
+
self.backgroundColor = [UIColor clearColor];
|
|
66
|
+
self.hidden = YES;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return self;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
- (void)updateProps:(const Props::Shared &)props
|
|
73
|
+
oldProps:(const Props::Shared &)oldProps {
|
|
74
|
+
const auto &newViewProps =
|
|
75
|
+
*std::static_pointer_cast<LuggCalloutViewProps const>(props);
|
|
76
|
+
|
|
77
|
+
_bubbled = newViewProps.bubbled;
|
|
78
|
+
|
|
79
|
+
if (oldProps) {
|
|
80
|
+
const auto &oldViewProps =
|
|
81
|
+
*std::static_pointer_cast<LuggCalloutViewProps const>(oldProps);
|
|
82
|
+
if (newViewProps.anchor.x != oldViewProps.anchor.x ||
|
|
83
|
+
newViewProps.anchor.y != oldViewProps.anchor.y) {
|
|
84
|
+
_anchor = CGPointMake(newViewProps.anchor.x, newViewProps.anchor.y);
|
|
85
|
+
}
|
|
86
|
+
} else if (newViewProps.anchor.x != 0 || newViewProps.anchor.y != 0) {
|
|
87
|
+
_anchor = CGPointMake(newViewProps.anchor.x, newViewProps.anchor.y);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[super updateProps:props oldProps:oldProps];
|
|
91
|
+
[_delegate calloutViewDidUpdate:self];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
- (BOOL)bubbled {
|
|
95
|
+
return _bubbled;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (CGPoint)anchor {
|
|
99
|
+
return _anchor;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
- (void)mountChildComponentView:
|
|
103
|
+
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
104
|
+
index:(NSInteger)index {
|
|
105
|
+
[_contentView insertSubview:childComponentView atIndex:index];
|
|
106
|
+
[_contentView updateContentSize];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
- (void)unmountChildComponentView:
|
|
110
|
+
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
111
|
+
index:(NSInteger)index {
|
|
112
|
+
[childComponentView removeFromSuperview];
|
|
113
|
+
[_contentView updateContentSize];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
- (void)layoutSubviews {
|
|
117
|
+
[super layoutSubviews];
|
|
118
|
+
CGSize oldSize = _contentView.bounds.size;
|
|
119
|
+
[_contentView updateContentSize];
|
|
120
|
+
CGSize newSize = _contentView.bounds.size;
|
|
121
|
+
if (!CGSizeEqualToSize(oldSize, newSize)) {
|
|
122
|
+
[_delegate calloutViewDidUpdate:self];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (BOOL)hasCustomContent {
|
|
127
|
+
return _contentView.subviews.count > 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
- (UIView *)contentView {
|
|
131
|
+
return _contentView;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
- (void)prepareForRecycle {
|
|
135
|
+
[super prepareForRecycle];
|
|
136
|
+
for (UIView *subview in _contentView.subviews) {
|
|
137
|
+
[subview removeFromSuperview];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Class<RCTComponentViewProtocol> LuggCalloutViewCls(void) {
|
|
142
|
+
return LuggCalloutView.class;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@end
|
package/ios/LuggMarkerView.h
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
NS_ASSUME_NONNULL_BEGIN
|
|
6
6
|
|
|
7
7
|
@class LuggMarkerView;
|
|
8
|
+
@class LuggCalloutView;
|
|
8
9
|
|
|
9
10
|
@protocol LuggMarkerViewDelegate <NSObject>
|
|
10
11
|
@optional
|
|
@@ -27,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
27
28
|
@property(nonatomic, readonly) BOOL hasCustomView;
|
|
28
29
|
@property(nonatomic, readonly) BOOL didLayout;
|
|
29
30
|
@property(nonatomic, readonly) UIView *iconView;
|
|
31
|
+
@property(nonatomic, readonly, nullable) LuggCalloutView *calloutView;
|
|
30
32
|
@property(nonatomic, weak, nullable) id<LuggMarkerViewDelegate> delegate;
|
|
31
33
|
@property(nonatomic, strong, nullable) NSObject *marker;
|
|
32
34
|
|
package/ios/LuggMarkerView.mm
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "LuggMarkerView.h"
|
|
2
|
+
#import "LuggCalloutView.h"
|
|
2
3
|
#import "events/MarkerDragEvent.h"
|
|
3
4
|
#import "events/MarkerPressEvent.h"
|
|
4
5
|
|
|
@@ -28,6 +29,7 @@ using namespace luggmaps::events;
|
|
|
28
29
|
BOOL _draggable;
|
|
29
30
|
BOOL _didLayout;
|
|
30
31
|
UIView *_iconView;
|
|
32
|
+
LuggCalloutView *_calloutView;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
@@ -92,14 +94,22 @@ using namespace luggmaps::events;
|
|
|
92
94
|
- (void)mountChildComponentView:
|
|
93
95
|
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
94
96
|
index:(NSInteger)index {
|
|
95
|
-
[
|
|
97
|
+
if ([childComponentView isKindOfClass:[LuggCalloutView class]]) {
|
|
98
|
+
_calloutView = (LuggCalloutView *)childComponentView;
|
|
99
|
+
} else {
|
|
100
|
+
[_iconView insertSubview:childComponentView atIndex:index];
|
|
101
|
+
}
|
|
96
102
|
_didLayout = NO;
|
|
97
103
|
}
|
|
98
104
|
|
|
99
105
|
- (void)unmountChildComponentView:
|
|
100
106
|
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
101
107
|
index:(NSInteger)index {
|
|
102
|
-
[childComponentView
|
|
108
|
+
if ([childComponentView isKindOfClass:[LuggCalloutView class]]) {
|
|
109
|
+
_calloutView = nil;
|
|
110
|
+
} else {
|
|
111
|
+
[childComponentView removeFromSuperview];
|
|
112
|
+
}
|
|
103
113
|
_didLayout = NO;
|
|
104
114
|
}
|
|
105
115
|
|
|
@@ -180,6 +190,10 @@ using namespace luggmaps::events;
|
|
|
180
190
|
return _iconView;
|
|
181
191
|
}
|
|
182
192
|
|
|
193
|
+
- (LuggCalloutView *)calloutView {
|
|
194
|
+
return _calloutView;
|
|
195
|
+
}
|
|
196
|
+
|
|
183
197
|
- (UIImage *)createIconImage {
|
|
184
198
|
CGSize size = _iconView.bounds.size;
|
|
185
199
|
if (size.width <= 0 || size.height <= 0) {
|
|
@@ -271,6 +285,7 @@ using namespace luggmaps::events;
|
|
|
271
285
|
- (void)prepareForRecycle {
|
|
272
286
|
[super prepareForRecycle];
|
|
273
287
|
_didLayout = NO;
|
|
288
|
+
_calloutView = nil;
|
|
274
289
|
self.marker = nil;
|
|
275
290
|
self.delegate = nil;
|
|
276
291
|
[self resetIconViewTransform];
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#import "AppleMapProvider.h"
|
|
2
|
+
#import "../LuggCalloutView.h"
|
|
2
3
|
#import "../LuggMarkerView.h"
|
|
3
4
|
#import "../LuggPolygonView.h"
|
|
4
5
|
#import "../LuggPolylineView.h"
|
|
5
6
|
#import "../extensions/MKMapView+Zoom.h"
|
|
7
|
+
#import "LuggAnnotationView.h"
|
|
6
8
|
#import "MKPolylineAnimator.h"
|
|
7
9
|
|
|
8
10
|
@interface AppleMarkerAnnotation : NSObject <MKAnnotation>
|
|
@@ -11,6 +13,7 @@
|
|
|
11
13
|
@property(nonatomic, copy, nullable) NSString *subtitle;
|
|
12
14
|
@property(nonatomic, strong) LuggMarkerView *markerView;
|
|
13
15
|
@property(nonatomic, weak) MKAnnotationView *annotationView;
|
|
16
|
+
@property(nonatomic, copy, nullable) dispatch_block_t pendingScaleAnimation;
|
|
14
17
|
@end
|
|
15
18
|
|
|
16
19
|
@implementation AppleMarkerAnnotation
|
|
@@ -20,11 +23,12 @@
|
|
|
20
23
|
@end
|
|
21
24
|
|
|
22
25
|
@interface AppleMapProvider () <
|
|
23
|
-
LuggMarkerViewDelegate,
|
|
24
|
-
UIGestureRecognizerDelegate>
|
|
26
|
+
LuggMarkerViewDelegate, LuggCalloutViewDelegate, LuggPolylineViewDelegate,
|
|
27
|
+
LuggPolygonViewDelegate, UIGestureRecognizerDelegate>
|
|
25
28
|
@end
|
|
26
29
|
|
|
27
30
|
@implementation AppleMapProvider {
|
|
31
|
+
UIView *_wrapperView;
|
|
28
32
|
LuggAppleMapViewContent *_mapView;
|
|
29
33
|
BOOL _isMapReady;
|
|
30
34
|
BOOL _isDragging;
|
|
@@ -34,6 +38,8 @@
|
|
|
34
38
|
NSMapTable<id<MKOverlay>, LuggPolygonView *> *_overlayToPolygonMap;
|
|
35
39
|
UITapGestureRecognizer *_tapGesture;
|
|
36
40
|
UILongPressGestureRecognizer *_longPressGesture;
|
|
41
|
+
LuggMarkerView *_activeNonBubbledMarker;
|
|
42
|
+
BOOL _isReselectingAnnotation;
|
|
37
43
|
// Edge insets animation
|
|
38
44
|
CADisplayLink *_edgeInsetsDisplayLink;
|
|
39
45
|
UIEdgeInsets _edgeInsetsFrom;
|
|
@@ -91,6 +97,7 @@
|
|
|
91
97
|
|
|
92
98
|
[_tapGesture requireGestureRecognizerToFail:_longPressGesture];
|
|
93
99
|
|
|
100
|
+
_wrapperView = wrapperView;
|
|
94
101
|
[wrapperView addSubview:_mapView];
|
|
95
102
|
|
|
96
103
|
MKCoordinateRegion region = [_mapView regionForCenterCoordinate:coordinate
|
|
@@ -103,6 +110,7 @@
|
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
- (void)destroy {
|
|
113
|
+
[self dismissNonBubbledCallout];
|
|
106
114
|
[self stopEdgeInsetsAnimation];
|
|
107
115
|
if (_tapGesture) {
|
|
108
116
|
[_mapView removeGestureRecognizer:_tapGesture];
|
|
@@ -319,11 +327,24 @@
|
|
|
319
327
|
return NO;
|
|
320
328
|
}
|
|
321
329
|
|
|
330
|
+
- (BOOL)hitTestCalloutAtPoint:(CGPoint)point {
|
|
331
|
+
if (!_activeNonBubbledMarker)
|
|
332
|
+
return NO;
|
|
333
|
+
|
|
334
|
+
UIView *contentView = _activeNonBubbledMarker.calloutView.contentView;
|
|
335
|
+
CGPoint local = [contentView convertPoint:point fromView:_mapView];
|
|
336
|
+
return [contentView pointInside:local withEvent:nil];
|
|
337
|
+
}
|
|
338
|
+
|
|
322
339
|
- (void)handleTap:(UITapGestureRecognizer *)gesture {
|
|
323
340
|
if (gesture.state != UIGestureRecognizerStateEnded)
|
|
324
341
|
return;
|
|
325
342
|
|
|
326
343
|
CGPoint point = [gesture locationInView:_mapView];
|
|
344
|
+
if ([self hitTestCalloutAtPoint:point])
|
|
345
|
+
return;
|
|
346
|
+
|
|
347
|
+
[self dismissNonBubbledCallout];
|
|
327
348
|
|
|
328
349
|
if ([self hitTestAnnotationAtPoint:point])
|
|
329
350
|
return;
|
|
@@ -390,6 +411,7 @@
|
|
|
390
411
|
longitude:mapView.centerCoordinate.longitude
|
|
391
412
|
zoom:mapView.zoomLevel
|
|
392
413
|
gesture:_isDragging];
|
|
414
|
+
[self positionNonBubbledCallout];
|
|
393
415
|
}
|
|
394
416
|
|
|
395
417
|
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
|
|
@@ -423,22 +445,23 @@
|
|
|
423
445
|
}
|
|
424
446
|
|
|
425
447
|
if (!markerView.hasCustomView) {
|
|
426
|
-
|
|
427
|
-
[[
|
|
428
|
-
|
|
448
|
+
LuggMarkerAnnotationView *markerAnnotationView =
|
|
449
|
+
[[LuggMarkerAnnotationView alloc] initWithAnnotation:annotation
|
|
450
|
+
reuseIdentifier:nil];
|
|
429
451
|
markerAnnotationView.canShowCallout = YES;
|
|
430
452
|
markerAnnotationView.displayPriority = MKFeatureDisplayPriorityRequired;
|
|
431
453
|
markerAnnotationView.layer.zPosition = markerView.zIndex;
|
|
432
454
|
markerAnnotationView.zPriority = markerView.zIndex;
|
|
433
455
|
markerAnnotationView.draggable = markerView.draggable;
|
|
456
|
+
[self applyCalloutView:markerView annotationView:markerAnnotationView];
|
|
434
457
|
[self addCenterTapGesture:markerAnnotationView];
|
|
435
458
|
markerAnnotation.annotationView = markerAnnotationView;
|
|
436
459
|
return markerAnnotationView;
|
|
437
460
|
}
|
|
438
461
|
|
|
439
|
-
|
|
440
|
-
[[
|
|
441
|
-
|
|
462
|
+
LuggAnnotationView *annotationView =
|
|
463
|
+
[[LuggAnnotationView alloc] initWithAnnotation:annotation
|
|
464
|
+
reuseIdentifier:nil];
|
|
442
465
|
annotationView.canShowCallout = YES;
|
|
443
466
|
annotationView.displayPriority = MKFeatureDisplayPriorityRequired;
|
|
444
467
|
annotationView.layer.zPosition = markerView.zIndex;
|
|
@@ -446,6 +469,8 @@
|
|
|
446
469
|
annotationView.draggable = markerView.draggable;
|
|
447
470
|
[self addCenterTapGesture:annotationView];
|
|
448
471
|
|
|
472
|
+
[self applyCalloutView:markerView annotationView:annotationView];
|
|
473
|
+
|
|
449
474
|
if (!markerView.rasterize) {
|
|
450
475
|
UIView *iconView = markerView.iconView;
|
|
451
476
|
[iconView removeFromSuperview];
|
|
@@ -516,6 +541,108 @@
|
|
|
516
541
|
CGPoint point = [_mapView convertCoordinate:markerView.coordinate
|
|
517
542
|
toPointToView:_mapView];
|
|
518
543
|
[markerView emitPressEventWithPoint:point];
|
|
544
|
+
|
|
545
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
546
|
+
if (calloutView && !calloutView.bubbled && calloutView.hasCustomContent) {
|
|
547
|
+
[self showNonBubbledCallout:markerView];
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
- (void)mapView:(MKMapView *)mapView
|
|
553
|
+
didDeselectAnnotationView:(MKAnnotationView *)view {
|
|
554
|
+
if (![view.annotation isKindOfClass:[AppleMarkerAnnotation class]])
|
|
555
|
+
return;
|
|
556
|
+
|
|
557
|
+
AppleMarkerAnnotation *annotation = (AppleMarkerAnnotation *)view.annotation;
|
|
558
|
+
LuggMarkerView *markerView = annotation.markerView;
|
|
559
|
+
|
|
560
|
+
if (markerView && _activeNonBubbledMarker == markerView &&
|
|
561
|
+
!_isReselectingAnnotation) {
|
|
562
|
+
_isReselectingAnnotation = YES;
|
|
563
|
+
[_mapView selectAnnotation:annotation animated:NO];
|
|
564
|
+
_isReselectingAnnotation = NO;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
- (void)showNonBubbledCallout:(LuggMarkerView *)markerView {
|
|
569
|
+
[self dismissNonBubbledCallout];
|
|
570
|
+
|
|
571
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
572
|
+
UIView *contentView = calloutView.contentView;
|
|
573
|
+
[contentView removeFromSuperview];
|
|
574
|
+
|
|
575
|
+
contentView.userInteractionEnabled = YES;
|
|
576
|
+
contentView.hidden = YES;
|
|
577
|
+
calloutView.delegate = self;
|
|
578
|
+
|
|
579
|
+
AppleMarkerAnnotation *annotation =
|
|
580
|
+
(AppleMarkerAnnotation *)markerView.marker;
|
|
581
|
+
MKAnnotationView *annotationView = annotation.annotationView;
|
|
582
|
+
if (annotationView) {
|
|
583
|
+
annotationView.clipsToBounds = NO;
|
|
584
|
+
[annotationView addSubview:contentView];
|
|
585
|
+
} else {
|
|
586
|
+
[_wrapperView addSubview:contentView];
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
_activeNonBubbledMarker = markerView;
|
|
590
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
591
|
+
[self positionNonBubbledCallout];
|
|
592
|
+
contentView.hidden = NO;
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
- (void)calloutViewDidUpdate:(LuggCalloutView *)calloutView {
|
|
597
|
+
[self positionNonBubbledCallout];
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
- (void)positionNonBubbledCallout {
|
|
601
|
+
if (!_activeNonBubbledMarker)
|
|
602
|
+
return;
|
|
603
|
+
|
|
604
|
+
LuggCalloutView *calloutView = _activeNonBubbledMarker.calloutView;
|
|
605
|
+
UIView *contentView = calloutView.contentView;
|
|
606
|
+
CGSize contentSize = contentView.bounds.size;
|
|
607
|
+
if (contentSize.width <= 0 || contentSize.height <= 0)
|
|
608
|
+
return;
|
|
609
|
+
|
|
610
|
+
CGPoint anchor = calloutView.anchor;
|
|
611
|
+
|
|
612
|
+
AppleMarkerAnnotation *annotation =
|
|
613
|
+
(AppleMarkerAnnotation *)_activeNonBubbledMarker.marker;
|
|
614
|
+
MKAnnotationView *annotationView = annotation.annotationView;
|
|
615
|
+
|
|
616
|
+
if (annotationView && contentView.superview == annotationView) {
|
|
617
|
+
CGPoint center = CGPointMake(annotationView.bounds.size.width / 2.0 +
|
|
618
|
+
contentSize.width * (0.5 - anchor.x),
|
|
619
|
+
annotationView.bounds.size.height / 2.0 +
|
|
620
|
+
contentSize.height * (0.5 - anchor.y));
|
|
621
|
+
contentView.center = center;
|
|
622
|
+
} else {
|
|
623
|
+
CGPoint point =
|
|
624
|
+
[_mapView convertCoordinate:_activeNonBubbledMarker.coordinate
|
|
625
|
+
toPointToView:_wrapperView];
|
|
626
|
+
contentView.center =
|
|
627
|
+
CGPointMake(point.x + contentSize.width * (0.5 - anchor.x),
|
|
628
|
+
point.y + contentSize.height * (0.5 - anchor.y));
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
- (void)dismissNonBubbledCallout {
|
|
633
|
+
if (!_activeNonBubbledMarker)
|
|
634
|
+
return;
|
|
635
|
+
|
|
636
|
+
LuggMarkerView *markerView = _activeNonBubbledMarker;
|
|
637
|
+
_activeNonBubbledMarker = nil;
|
|
638
|
+
|
|
639
|
+
markerView.calloutView.delegate = nil;
|
|
640
|
+
[markerView.calloutView.contentView removeFromSuperview];
|
|
641
|
+
|
|
642
|
+
AppleMarkerAnnotation *annotation =
|
|
643
|
+
(AppleMarkerAnnotation *)markerView.marker;
|
|
644
|
+
if (annotation) {
|
|
645
|
+
[_mapView deselectAnnotation:annotation animated:NO];
|
|
519
646
|
}
|
|
520
647
|
}
|
|
521
648
|
|
|
@@ -574,6 +701,27 @@
|
|
|
574
701
|
}
|
|
575
702
|
}
|
|
576
703
|
|
|
704
|
+
- (void)applyCalloutView:(LuggMarkerView *)markerView
|
|
705
|
+
annotationView:(MKAnnotationView *)annotationView {
|
|
706
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
707
|
+
if (!calloutView) {
|
|
708
|
+
annotationView.detailCalloutAccessoryView = nil;
|
|
709
|
+
annotationView.rightCalloutAccessoryView = nil;
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
annotationView.rightCalloutAccessoryView = nil;
|
|
714
|
+
|
|
715
|
+
if (!calloutView.bubbled) {
|
|
716
|
+
annotationView.canShowCallout = NO;
|
|
717
|
+
annotationView.detailCalloutAccessoryView = nil;
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
annotationView.detailCalloutAccessoryView =
|
|
722
|
+
calloutView.hasCustomContent ? calloutView.contentView : nil;
|
|
723
|
+
}
|
|
724
|
+
|
|
577
725
|
#pragma mark - MarkerViewDelegate
|
|
578
726
|
|
|
579
727
|
- (void)markerViewDidLayout:(LuggMarkerView *)markerView {
|
|
@@ -600,6 +748,7 @@
|
|
|
600
748
|
annotationView.draggable = markerView.draggable;
|
|
601
749
|
annotationView.layer.zPosition = markerView.zIndex;
|
|
602
750
|
annotationView.zPriority = markerView.zIndex;
|
|
751
|
+
[self applyCalloutView:markerView annotationView:annotationView];
|
|
603
752
|
}
|
|
604
753
|
|
|
605
754
|
[self updateAnnotationViewFrame:annotation];
|
|
@@ -640,6 +789,10 @@
|
|
|
640
789
|
(AppleMarkerAnnotation *)markerView.marker;
|
|
641
790
|
|
|
642
791
|
if (annotation) {
|
|
792
|
+
if (annotation.pendingScaleAnimation) {
|
|
793
|
+
dispatch_block_cancel(annotation.pendingScaleAnimation);
|
|
794
|
+
annotation.pendingScaleAnimation = nil;
|
|
795
|
+
}
|
|
643
796
|
annotation.annotationView.transform = CGAffineTransformIdentity;
|
|
644
797
|
annotation.markerView = nil;
|
|
645
798
|
annotation.annotationView = nil;
|
|
@@ -658,31 +811,65 @@
|
|
|
658
811
|
annotationView.transform = CGAffineTransformIdentity;
|
|
659
812
|
|
|
660
813
|
UIView *iconView = markerView.iconView;
|
|
661
|
-
|
|
662
|
-
|
|
814
|
+
iconView.transform = CGAffineTransformIdentity;
|
|
815
|
+
|
|
816
|
+
// Clean up iconView from in-progress rasterize animation
|
|
817
|
+
if (markerView.rasterize && [iconView superview] == annotationView) {
|
|
818
|
+
[iconView removeFromSuperview];
|
|
819
|
+
iconView.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
CGSize size = iconView.bounds.size;
|
|
823
|
+
if (size.width <= 0 || size.height <= 0)
|
|
663
824
|
return;
|
|
664
825
|
|
|
665
826
|
CGFloat scale = markerView.scale;
|
|
666
827
|
CGPoint anchor = markerView.anchor;
|
|
828
|
+
CGFloat scaledWidth = size.width * scale;
|
|
829
|
+
CGFloat scaledHeight = size.height * scale;
|
|
667
830
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
831
|
+
AppleMarkerAnnotation *annotation =
|
|
832
|
+
(AppleMarkerAnnotation *)markerView.marker;
|
|
833
|
+
|
|
834
|
+
// Cancel any pending rasterize
|
|
835
|
+
if (annotation.pendingScaleAnimation) {
|
|
836
|
+
dispatch_block_cancel(annotation.pendingScaleAnimation);
|
|
837
|
+
annotation.pendingScaleAnimation = nil;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Use live iconView during rapid updates (skip expensive rasterize per frame)
|
|
841
|
+
if (markerView.rasterize && [iconView superview] != annotationView) {
|
|
842
|
+
annotationView.image = nil;
|
|
843
|
+
[annotationView addSubview:iconView];
|
|
677
844
|
}
|
|
678
845
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
CGPointMake(
|
|
683
|
-
|
|
846
|
+
iconView.layer.anchorPoint = anchor;
|
|
847
|
+
iconView.bounds = CGRectMake(0, 0, size.width, size.height);
|
|
848
|
+
iconView.center =
|
|
849
|
+
CGPointMake(scaledWidth * anchor.x, scaledHeight * anchor.y);
|
|
850
|
+
iconView.transform = CGAffineTransformMakeScale(scale, scale);
|
|
851
|
+
|
|
852
|
+
annotationView.bounds = CGRectMake(0, 0, scaledWidth, scaledHeight);
|
|
853
|
+
annotationView.centerOffset = CGPointMake(scaledWidth * (0.5 - anchor.x),
|
|
854
|
+
scaledHeight * (0.5 - anchor.y));
|
|
684
855
|
annotationView.transform =
|
|
685
856
|
CGAffineTransformMakeRotation(markerView.rotate * M_PI / 180.0);
|
|
857
|
+
|
|
858
|
+
// Debounce: rasterize once updates settle
|
|
859
|
+
if (markerView.rasterize) {
|
|
860
|
+
dispatch_block_t rasterizeBlock =
|
|
861
|
+
dispatch_block_create((dispatch_block_flags_t)0, ^{
|
|
862
|
+
annotation.pendingScaleAnimation = nil;
|
|
863
|
+
annotationView.image = [markerView createScaledIconImage];
|
|
864
|
+
[iconView removeFromSuperview];
|
|
865
|
+
[markerView resetIconViewTransform];
|
|
866
|
+
});
|
|
867
|
+
|
|
868
|
+
annotation.pendingScaleAnimation = rasterizeBlock;
|
|
869
|
+
dispatch_after(
|
|
870
|
+
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(150 * NSEC_PER_MSEC)),
|
|
871
|
+
dispatch_get_main_queue(), rasterizeBlock);
|
|
872
|
+
}
|
|
686
873
|
}
|
|
687
874
|
|
|
688
875
|
- (void)updateAnnotationViewFrame:(AppleMarkerAnnotation *)annotation {
|