diff --git a/ClusterKit/Core/CKCluster.h b/ClusterKit/Core/CKCluster.h index ea89dac..17e6f91 100644 --- a/ClusterKit/Core/CKCluster.h +++ b/ClusterKit/Core/CKCluster.h @@ -65,7 +65,7 @@ MK_EXTERN NSComparisonResult MKMapSizeCompare(MKMapSize size1, MKMapSize size2); /** Cluster coordinate. */ -@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; +@property (nonatomic) CLLocationCoordinate2D coordinate; /** Cluster annotation array. diff --git a/ClusterKit/Core/CKClusterManager.h b/ClusterKit/Core/CKClusterManager.h index c23e4bd..b39b9c2 100644 --- a/ClusterKit/Core/CKClusterManager.h +++ b/ClusterKit/Core/CKClusterManager.h @@ -31,6 +31,7 @@ FOUNDATION_EXTERN const double kCKMarginFactorWorld; @protocol CKMap; @class CKClusterManager; +@class CKClusterAnimation; /** The delegate of a CKClusterManager object may adopt the CKClusterManagerDelegate protocol. @@ -50,6 +51,15 @@ FOUNDATION_EXTERN const double kCKMarginFactorWorld; */ - (BOOL)clusterManager:(CKClusterManager *)clusterManager shouldClusterAnnotation:(id)annotation; +/** + Tells the delegate to perform a custom animation based on the animations array. + + @param clusterManager The cluster manager object requesting the animation. + @param customAnimations An array of CKClusterAnimation objects containing the animations. This parameter must not be NULL. + @param completion A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be NULL. + */ +- (void)clusterManager:(CKClusterManager *)clusterManager performCustomAnimations:(NSArray *)animations completion:(void (^ __nullable)(BOOL finished))completion; + /** Tells the delegate to perform an animation. @@ -169,6 +179,14 @@ FOUNDATION_EXTERN const double kCKMarginFactorWorld; @end +/** +CKClusterAnimationType defines the type of the CKClusterAnimation object. +*/ +typedef NS_ENUM(NSInteger, CKClusterAnimationType) { + CKClusterAnimationTypeCollapse, + CKClusterAnimationTypeExpand +}; + /** CKClusterAnimation defines a cluster animation from a start coordinate to an end coordinate on a map. */ @@ -189,15 +207,21 @@ FOUNDATION_EXTERN const double kCKMarginFactorWorld; */ @property (nonatomic) CLLocationCoordinate2D to; +/** +The type of the animation. +*/ +@property (nonatomic) CKClusterAnimationType type; + /** Initializes an animation for the given cluster. @param cluster The cluster to animate. @param from The cluster starting point. @param to The cluster ending point. + @param type The type of the animation. @return The initialized CKClusterAnimation object. */ -- (instancetype)initWithCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to type:(CKClusterAnimationType)type NS_DESIGNATED_INITIALIZER; /** Creates an animation for the given cluster. @@ -205,9 +229,10 @@ FOUNDATION_EXTERN const double kCKMarginFactorWorld; @param cluster The cluster to animate. @param from The cluster starting point. @param to The cluster ending point. + @param type The type of the animation. @return The initialized CKClusterAnimation object. */ -+ (instancetype)animateCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to; ++ (instancetype)animateCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to type:(CKClusterAnimationType)type; /// :nodoc: - (instancetype)init NS_UNAVAILABLE; diff --git a/ClusterKit/Core/CKClusterManager.m b/ClusterKit/Core/CKClusterManager.m index 5582383..24b7cf3 100644 --- a/ClusterKit/Core/CKClusterManager.m +++ b/ClusterKit/Core/CKClusterManager.m @@ -254,7 +254,7 @@ - (void)expand:(NSArray *)newClusters from:(NSArray *) CKClusterAnimation *animation = [animations member:neighbor]; if (!animation) { - animation = [CKClusterAnimation animateCluster:neighbor from:oldCluster.coordinate to:neighbor.coordinate]; + animation = [CKClusterAnimation animateCluster:neighbor from:oldCluster.coordinate to:neighbor.coordinate type:CKClusterAnimationTypeExpand]; [animations addObject:animation]; continue; } @@ -290,7 +290,7 @@ - (void)collapse:(NSArray *)oldClusters to:(NSArray *) CKClusterAnimation *animation = [animations member:neighbor]; if (!animation) { - animation = [CKClusterAnimation animateCluster:neighbor from:neighbor.coordinate to:newCluster.coordinate]; + animation = [CKClusterAnimation animateCluster:neighbor from:neighbor.coordinate to:newCluster.coordinate type:CKClusterAnimationTypeCollapse]; [animations addObject:animation]; continue; } @@ -325,16 +325,17 @@ - (BOOL)annotationTree:(id)annotationTree shouldExtractAnnotat @implementation CKClusterAnimation -+ (instancetype)animateCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to { - return [[self alloc] initWithCluster:cluster from:from to:to]; ++ (instancetype)animateCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to type:(CKClusterAnimationType)type { + return [[self alloc] initWithCluster:cluster from:from to:to type:type]; } -- (instancetype)initWithCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to { +- (instancetype)initWithCluster:(CKCluster *)cluster from:(CLLocationCoordinate2D)from to:(CLLocationCoordinate2D)to type:(CKClusterAnimationType)type { self = [super init]; if (self) { _cluster = cluster; _from = from; _to = to; + _type = type; } return self; } diff --git a/ClusterKit/Mapbox/MGLMapView+ClusterKit.m b/ClusterKit/Mapbox/MGLMapView+ClusterKit.m index df9da34..a6e6895 100644 --- a/ClusterKit/Mapbox/MGLMapView+ClusterKit.m +++ b/ClusterKit/Mapbox/MGLMapView+ClusterKit.m @@ -138,7 +138,13 @@ - (void)performAnimations:(NSArray *)animations completion }; } - if ([self.clusterManager.delegate respondsToSelector:@selector(clusterManager:performAnimations:completion:)]) { + if ([self.clusterManager.delegate respondsToSelector:@selector(clusterManager:performCustomAnimations:completion:)]) { + [self.clusterManager.delegate clusterManager:self.clusterManager + performCustomAnimations:animations + completion:^(BOOL finished) { + if (completion) completion(finished); + }]; + } else if ([self.clusterManager.delegate respondsToSelector:@selector(clusterManager:performAnimations:completion:)]) { [self.clusterManager.delegate clusterManager:self.clusterManager performAnimations:animationsBlock completion:^(BOOL finished) {