@ -0,0 +1,20 @@ |
|||||||
|
//
|
||||||
|
// CLAnimatedImages.h
|
||||||
|
//
|
||||||
|
// Code generated using QuartzCode 1.39.16 on 5/10/16.
|
||||||
|
// www.quartzcodeapp.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h> |
||||||
|
|
||||||
|
IB_DESIGNABLE |
||||||
|
@interface CLAnimatedImages : NSView |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- (void)addUntitled1Animation; |
||||||
|
- (void)addUntitled1AnimationCompletionBlock:(void (^)(BOOL finished))completionBlock; |
||||||
|
- (void)removeAnimationsForAnimationId:(NSString *)identifier; |
||||||
|
- (void)removeAllAnimations; |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,241 @@ |
|||||||
|
// |
||||||
|
// CLAnimatedImages.m |
||||||
|
// |
||||||
|
// Code generated using QuartzCode 1.39.16 on 5/10/16. |
||||||
|
// www.quartzcodeapp.com |
||||||
|
// |
||||||
|
|
||||||
|
#import "CLAnimatedImages.h" |
||||||
|
#import "QCMethod.h" |
||||||
|
|
||||||
|
@interface CLAnimatedImages () |
||||||
|
|
||||||
|
@property (nonatomic, strong) NSMutableDictionary * layers; |
||||||
|
@property (nonatomic, strong) NSMapTable * completionBlocks; |
||||||
|
@property (nonatomic, assign) BOOL updateLayerValueForCompletedAnimation; |
||||||
|
|
||||||
|
|
||||||
|
@end |
||||||
|
|
||||||
|
@implementation CLAnimatedImages |
||||||
|
|
||||||
|
#pragma mark - Life Cycle |
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame |
||||||
|
{ |
||||||
|
self = [super initWithFrame:frame]; |
||||||
|
if (self) { |
||||||
|
[self setupProperties]; |
||||||
|
[self setupLayers]; |
||||||
|
} |
||||||
|
return self; |
||||||
|
} |
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)coder |
||||||
|
{ |
||||||
|
self = [super initWithCoder:coder]; |
||||||
|
if (self) { |
||||||
|
[self setupProperties]; |
||||||
|
[self setupLayers]; |
||||||
|
} |
||||||
|
return self; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- (void)setupProperties{ |
||||||
|
self.completionBlocks = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsOpaqueMemory valueOptions:NSPointerFunctionsStrongMemory];; |
||||||
|
self.layers = [NSMutableDictionary dictionary]; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
- (void)setupLayers{ |
||||||
|
[self setWantsLayer:YES]; |
||||||
|
|
||||||
|
CALayer * effect = [CALayer layer]; |
||||||
|
effect.frame = CGRectMake(25.09, 4.93, 230.89, 203.84); |
||||||
|
[self.layer addSublayer:effect]; |
||||||
|
self.layers[@"effect"] = effect; |
||||||
|
//effect effect layer setup |
||||||
|
{ |
||||||
|
CALayer * TopPlaces = [CALayer layer]; |
||||||
|
TopPlaces.frame = CGRectMake(0, -0, 66, 57.02); |
||||||
|
[effect addSublayer:TopPlaces]; |
||||||
|
self.layers[@"TopPlaces"] = TopPlaces; |
||||||
|
CALayer * TopPlaces2 = [CALayer layer]; |
||||||
|
TopPlaces2.frame = CGRectMake(82.46, -0, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces2]; |
||||||
|
self.layers[@"TopPlaces2"] = TopPlaces2; |
||||||
|
CALayer * TopPlaces3 = [CALayer layer]; |
||||||
|
TopPlaces3.frame = CGRectMake(164.92, -0, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces3]; |
||||||
|
self.layers[@"TopPlaces3"] = TopPlaces3; |
||||||
|
CALayer * TopPlaces4 = [CALayer layer]; |
||||||
|
TopPlaces4.frame = CGRectMake(0, 73.43, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces4]; |
||||||
|
self.layers[@"TopPlaces4"] = TopPlaces4; |
||||||
|
CALayer * TopPlaces5 = [CALayer layer]; |
||||||
|
TopPlaces5.frame = CGRectMake(82.46, 73.43, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces5]; |
||||||
|
self.layers[@"TopPlaces5"] = TopPlaces5; |
||||||
|
CALayer * TopPlaces6 = [CALayer layer]; |
||||||
|
TopPlaces6.frame = CGRectMake(164.92, 73.43, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces6]; |
||||||
|
self.layers[@"TopPlaces6"] = TopPlaces6; |
||||||
|
CALayer * TopPlaces7 = [CALayer layer]; |
||||||
|
TopPlaces7.frame = CGRectMake(0, 146.86, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces7]; |
||||||
|
self.layers[@"TopPlaces7"] = TopPlaces7; |
||||||
|
CALayer * TopPlaces8 = [CALayer layer]; |
||||||
|
TopPlaces8.frame = CGRectMake(82.46, 146.86, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces8]; |
||||||
|
self.layers[@"TopPlaces8"] = TopPlaces8; |
||||||
|
CALayer * TopPlaces9 = [CALayer layer]; |
||||||
|
TopPlaces9.frame = CGRectMake(164.92, 146.86, 65.97, 56.99); |
||||||
|
[effect addSublayer:TopPlaces9]; |
||||||
|
self.layers[@"TopPlaces9"] = TopPlaces9; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[self resetLayerPropertiesForLayerIdentifiers:nil]; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)resetLayerPropertiesForLayerIdentifiers:(NSArray *)layerIds{ |
||||||
|
[CATransaction begin]; |
||||||
|
[CATransaction setDisableActions:YES]; |
||||||
|
|
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces"]){ |
||||||
|
CALayer * TopPlaces = self.layers[@"TopPlaces"]; |
||||||
|
TopPlaces.masksToBounds = YES; |
||||||
|
TopPlaces.contents = [NSImage imageNamed:@"Tokyo"]; |
||||||
|
TopPlaces.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces2"]){ |
||||||
|
CALayer * TopPlaces2 = self.layers[@"TopPlaces2"]; |
||||||
|
TopPlaces2.masksToBounds = YES; |
||||||
|
TopPlaces2.contents = [NSImage imageNamed:@"london"]; |
||||||
|
TopPlaces2.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces3"]){ |
||||||
|
CALayer * TopPlaces3 = self.layers[@"TopPlaces3"]; |
||||||
|
TopPlaces3.masksToBounds = YES; |
||||||
|
TopPlaces3.contents = [NSImage imageNamed:@"SF"]; |
||||||
|
TopPlaces3.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces4"]){ |
||||||
|
CALayer * TopPlaces4 = self.layers[@"TopPlaces4"]; |
||||||
|
TopPlaces4.masksToBounds = YES; |
||||||
|
TopPlaces4.contents = [NSImage imageNamed:@"LA"]; |
||||||
|
TopPlaces4.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces5"]){ |
||||||
|
CALayer * TopPlaces5 = self.layers[@"TopPlaces5"]; |
||||||
|
TopPlaces5.masksToBounds = YES; |
||||||
|
TopPlaces5.contents = [NSImage imageNamed:@"sydney"]; |
||||||
|
TopPlaces5.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces6"]){ |
||||||
|
CALayer * TopPlaces6 = self.layers[@"TopPlaces6"]; |
||||||
|
TopPlaces6.masksToBounds = YES; |
||||||
|
TopPlaces6.contents = [NSImage imageNamed:@"Singapore"]; |
||||||
|
TopPlaces6.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces7"]){ |
||||||
|
CALayer * TopPlaces7 = self.layers[@"TopPlaces7"]; |
||||||
|
TopPlaces7.masksToBounds = YES; |
||||||
|
TopPlaces7.contents = [NSImage imageNamed:@"NYC"]; |
||||||
|
TopPlaces7.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces8"]){ |
||||||
|
CALayer * TopPlaces8 = self.layers[@"TopPlaces8"]; |
||||||
|
TopPlaces8.masksToBounds = YES; |
||||||
|
TopPlaces8.contents = [NSImage imageNamed:@"HongKong"]; |
||||||
|
TopPlaces8.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
if(!layerIds || [layerIds containsObject:@"TopPlaces9"]){ |
||||||
|
CALayer * TopPlaces9 = self.layers[@"TopPlaces9"]; |
||||||
|
TopPlaces9.masksToBounds = YES; |
||||||
|
TopPlaces9.contents = [NSImage imageNamed:@"Paris"]; |
||||||
|
TopPlaces9.contentsGravity = kCAGravityResizeAspectFill; |
||||||
|
} |
||||||
|
|
||||||
|
[CATransaction commit]; |
||||||
|
} |
||||||
|
|
||||||
|
#pragma mark - Animation Setup |
||||||
|
|
||||||
|
- (void)addUntitled1Animation{ |
||||||
|
[self addUntitled1AnimationCompletionBlock:nil]; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)addUntitled1AnimationCompletionBlock:(void (^)(BOOL finished))completionBlock{ |
||||||
|
if (completionBlock){ |
||||||
|
CABasicAnimation * completionAnim = [CABasicAnimation animationWithKeyPath:@"completionAnim"];; |
||||||
|
completionAnim.duration = 4.2; |
||||||
|
completionAnim.delegate = self; |
||||||
|
[completionAnim setValue:@"Untitled1" forKey:@"animId"]; |
||||||
|
[completionAnim setValue:@(NO) forKey:@"needEndAnim"]; |
||||||
|
[self.layer addAnimation:completionAnim forKey:@"Untitled1"]; |
||||||
|
[self.completionBlocks setObject:completionBlock forKey:[self.layer animationForKey:@"Untitled1"]]; |
||||||
|
} |
||||||
|
|
||||||
|
NSString * fillMode = kCAFillModeForwards; |
||||||
|
|
||||||
|
////Effect animation |
||||||
|
CAKeyframeAnimation * effectTransformAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; |
||||||
|
effectTransformAnim.values = @[[NSValue valueWithCATransform3D:CATransform3DIdentity], |
||||||
|
[NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(-3 * M_PI/180, -0, -0, 1))], |
||||||
|
[NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeScale(1.5, 1.5, 1), CATransform3DMakeRotation(3 * M_PI/180, 0, 0, 1))]]; |
||||||
|
effectTransformAnim.keyTimes = @[@0, @0.44, @1]; |
||||||
|
effectTransformAnim.duration = 0.5; |
||||||
|
effectTransformAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; |
||||||
|
effectTransformAnim.autoreverses = YES; |
||||||
|
[effectTransformAnim setValue:@0.4 forKeyPath:@"instanceDelay"]; |
||||||
|
[effectTransformAnim setValue:@0 forKeyPath:@"instanceOrder"]; |
||||||
|
|
||||||
|
CABasicAnimation * effectZPositionAnim = [CABasicAnimation animationWithKeyPath:@"zPosition"]; |
||||||
|
effectZPositionAnim.fromValue = @0; |
||||||
|
effectZPositionAnim.toValue = @100; |
||||||
|
effectZPositionAnim.duration = 0.5; |
||||||
|
effectZPositionAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; |
||||||
|
effectZPositionAnim.autoreverses = YES; |
||||||
|
[effectZPositionAnim setValue:@0.4 forKeyPath:@"instanceDelay"]; |
||||||
|
[effectZPositionAnim setValue:@0 forKeyPath:@"instanceOrder"]; |
||||||
|
|
||||||
|
CAAnimationGroup * effectUntitled1Anim = [QCMethod groupAnimations:@[effectTransformAnim, effectZPositionAnim] fillMode:kCAFillModeBoth forEffectLayer:YES sublayersCount:9]; |
||||||
|
[QCMethod addSublayersAnimation:effectUntitled1Anim forKey:@"effectUntitled1Anim" forLayer:(CALayer *)self.layers[@"effect"]]; |
||||||
|
} |
||||||
|
|
||||||
|
#pragma mark - Animation Cleanup |
||||||
|
|
||||||
|
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ |
||||||
|
void (^completionBlock)(BOOL) = [self.completionBlocks objectForKey:anim];; |
||||||
|
if (completionBlock){ |
||||||
|
[self.completionBlocks removeObjectForKey:anim]; |
||||||
|
if ((flag && self.updateLayerValueForCompletedAnimation) || [[anim valueForKey:@"needEndAnim"] boolValue]){ |
||||||
|
[self updateLayerValuesForAnimationId:[anim valueForKey:@"animId"]]; |
||||||
|
[self removeAnimationsForAnimationId:[anim valueForKey:@"animId"]]; |
||||||
|
} |
||||||
|
completionBlock(flag); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- (void)updateLayerValuesForAnimationId:(NSString *)identifier{ |
||||||
|
if([identifier isEqualToString:@"Untitled1"]){ |
||||||
|
[QCMethod updateValueFromPresentationLayerForAnimation:[self.layers[@"effect"] animationForKey:@"effectUntitled1Anim"] theLayer:self.layers[@"effect"]]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- (void)removeAnimationsForAnimationId:(NSString *)identifier{ |
||||||
|
if([identifier isEqualToString:@"Untitled1"]){ |
||||||
|
[self.layers[@"effect"] removeAnimationForKey:@"effectUntitled1Anim"]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- (void)removeAllAnimations{ |
||||||
|
[self.layers enumerateKeysAndObjectsUsingBlock:^(id key, CALayer *layer, BOOL *stop) { |
||||||
|
[layer removeAllAnimations]; |
||||||
|
}]; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,16 @@ |
|||||||
|
//
|
||||||
|
// CLArrowIndicators.h
|
||||||
|
// Clocker
|
||||||
|
//
|
||||||
|
// Created by Abhishek Banthia on 5/9/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h> |
||||||
|
|
||||||
|
@interface CLArrowIndicators : NSControl |
||||||
|
|
||||||
|
@property (strong, nonatomic) NSColor *blackColor; |
||||||
|
@property (assign, nonatomic) BOOL mouseDown; |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,66 @@ |
|||||||
|
// |
||||||
|
// CLArrowIndicators.m |
||||||
|
// Clocker |
||||||
|
// |
||||||
|
// Created by Abhishek Banthia on 5/9/16. |
||||||
|
// |
||||||
|
// |
||||||
|
|
||||||
|
#import "CLArrowIndicators.h" |
||||||
|
|
||||||
|
typedef enum : NSUInteger { |
||||||
|
Left, |
||||||
|
Right |
||||||
|
} Type; |
||||||
|
|
||||||
|
@implementation CLArrowIndicators |
||||||
|
|
||||||
|
- (void)drawRect:(NSRect)dirtyRect { |
||||||
|
[super drawRect:dirtyRect]; |
||||||
|
|
||||||
|
// let drawRightArrow = self.type == .Right |
||||||
|
// let lineWidth: CGFloat = 4 |
||||||
|
// |
||||||
|
// let bezierPath = NSBezierPath() |
||||||
|
// bezierPath.moveToPoint(NSPoint(x: drawRightArrow ? NSMinX(self.bounds) : NSMaxX(self.bounds), y: NSMaxY(self.bounds))) |
||||||
|
// bezierPath.lineToPoint(NSPoint(x: drawRightArrow ? NSMaxX(self.bounds)-lineWidth*0.5 : NSMinX(self.bounds)+lineWidth*0.5, y: NSMidY(self.bounds))) |
||||||
|
// bezierPath.lineToPoint(NSPoint(x: drawRightArrow ? NSMinX(self.bounds) : NSMaxX(self.bounds), y: NSMinY(self.bounds))) |
||||||
|
// bezierPath.lineWidth = lineWidth |
||||||
|
// bezierPath.lineCapStyle = .RoundLineCapStyle |
||||||
|
// bezierPath.lineJoinStyle = .RoundLineJoinStyle |
||||||
|
// (self.mouseDown ? self.color : self.color.colorWithAlphaComponent(0.33)).setStroke() |
||||||
|
// bezierPath.stroke() |
||||||
|
|
||||||
|
Type drawRightArrow = Right; |
||||||
|
CGFloat lineWidth = 4; |
||||||
|
|
||||||
|
NSBezierPath *bezierPath = [[NSBezierPath alloc] init]; |
||||||
|
[bezierPath moveToPoint:NSMakePoint(drawRightArrow ? NSMinX(self.bounds) : NSMaxX(self.bounds), NSMaxY(self.bounds))]; |
||||||
|
[bezierPath lineToPoint:NSMakePoint(drawRightArrow ? NSMaxX(self.bounds) - lineWidth*0.5 : NSMinX(self.bounds) + lineWidth*0.5, NSMidY(self.bounds))]; |
||||||
|
[bezierPath lineToPoint:NSMakePoint(drawRightArrow ? NSMinX(self.bounds) : NSMaxX(self.bounds), NSMidY(self.bounds))]; |
||||||
|
bezierPath.lineWidth = lineWidth; |
||||||
|
bezierPath.lineCapStyle = NSRoundLineCapStyle; |
||||||
|
bezierPath.lineJoinStyle = NSRoundLineJoinStyle; |
||||||
|
self.mouseDown ? self.blackColor : [[self.blackColor colorWithAlphaComponent:0.33] setStroke]; |
||||||
|
[bezierPath stroke]; |
||||||
|
|
||||||
|
|
||||||
|
// Drawing code here. |
||||||
|
} |
||||||
|
|
||||||
|
- (void)mouseDown:(NSEvent *)theEvent |
||||||
|
{ |
||||||
|
[super mouseDown:theEvent]; |
||||||
|
self.mouseDown = YES; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)mouseUp:(NSEvent *)theEvent |
||||||
|
{ |
||||||
|
[super mouseUp:theEvent]; |
||||||
|
|
||||||
|
self.mouseDown = NO; |
||||||
|
|
||||||
|
[NSApp sendAction:self.action to:self.target from:self]; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,15 @@ |
|||||||
|
//
|
||||||
|
// CLScaleUpButton.h
|
||||||
|
// Clocker
|
||||||
|
//
|
||||||
|
// Created by Abhishek Banthia on 5/9/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h> |
||||||
|
|
||||||
|
@interface CLScaleUpButton : NSButton |
||||||
|
|
||||||
|
@property (strong, nonatomic) NSTrackingArea *trackingArea; |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,45 @@ |
|||||||
|
// |
||||||
|
// CLScaleUpButton.m |
||||||
|
// Clocker |
||||||
|
// |
||||||
|
// Created by Abhishek Banthia on 5/9/16. |
||||||
|
// |
||||||
|
// |
||||||
|
|
||||||
|
#import "CLScaleUpButton.h" |
||||||
|
#import <pop/POP.h> |
||||||
|
|
||||||
|
@implementation CLScaleUpButton |
||||||
|
|
||||||
|
- (void)drawRect:(NSRect)dirtyRect { |
||||||
|
[super drawRect:dirtyRect]; |
||||||
|
|
||||||
|
// Drawing code here. |
||||||
|
} |
||||||
|
|
||||||
|
-(void)mouseEntered:(NSEvent *)theEvent |
||||||
|
{ |
||||||
|
[super mouseEntered:theEvent]; |
||||||
|
|
||||||
|
POPSpringAnimation *scale = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; |
||||||
|
scale.velocity = [NSValue valueWithCGPoint:CGPointMake(1, 1)]; |
||||||
|
scale.springBounciness = 20.f; |
||||||
|
|
||||||
|
[self.layer pop_addAnimation:scale forKey:@"scale"]; |
||||||
|
} |
||||||
|
|
||||||
|
-(void)updateTrackingAreas |
||||||
|
{ |
||||||
|
if(self.trackingArea != nil) { |
||||||
|
[self removeTrackingArea:self.trackingArea]; |
||||||
|
} |
||||||
|
|
||||||
|
int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways); |
||||||
|
self.trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds] |
||||||
|
options:opts |
||||||
|
owner:self |
||||||
|
userInfo:nil]; |
||||||
|
[self addTrackingArea:self.trackingArea]; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,51 @@ |
|||||||
|
//
|
||||||
|
// QCMethod.h
|
||||||
|
//
|
||||||
|
// Version 1.2
|
||||||
|
//
|
||||||
|
// www.quartzcodeapp.com
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "TargetConditionals.h" |
||||||
|
#import <QuartzCore/QuartzCore.h> |
||||||
|
|
||||||
|
#if (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE) |
||||||
|
#import <UIKit/UIKit.h> |
||||||
|
#else |
||||||
|
#import <Cocoa/Cocoa.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
@interface QCMethod : NSObject |
||||||
|
+ (CAAnimation*)reverseAnimation:(CAAnimation*)anim totalDuration:(CGFloat)totalDuration; |
||||||
|
+ (CAAnimationGroup*)groupAnimations:(NSArray*)animations fillMode:(NSString*)fillMode forEffectLayer:(BOOL)forEffectLayer sublayersCount:(NSInteger)count; |
||||||
|
+ (CAAnimationGroup*)groupAnimations:(NSArray*)animations fillMode:(NSString*)fillMode; |
||||||
|
+ (CGFloat)maxDurationFromAnimations:(NSArray*)anims; |
||||||
|
+ (CGFloat)maxDurationOfEffectAnimation:(CAAnimationGroup*)anim sublayersCount:(NSInteger)count; |
||||||
|
+ (void)updateValueFromAnimationsForLayers:(NSArray*)layers; |
||||||
|
+ (void)updateValueForAnimation:(CAAnimation*)anim theLayer:(CALayer *)layer; |
||||||
|
+ (void)updateValueFromPresentationLayerForAnimation:(CAAnimation*)anim theLayer:(CALayer *)layer; |
||||||
|
+ (void)addSublayersAnimation:(CAAnimation*)anim forKey:(NSString*)key forLayer:(CALayer*)layer; |
||||||
|
+ (void)addSublayersAnimationNeedReverse:(CAAnimation*)anim forKey:(NSString*)key forLayer:(CALayer*)layer reverseAnimation:(BOOL)reverse totalDuration:(CGFloat)totalDuration; |
||||||
|
|
||||||
|
#if (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE) |
||||||
|
+ (UIBezierPath*)alignToBottomPath:(UIBezierPath*)path layer:(CALayer*)layer; |
||||||
|
+ (UIBezierPath*)offsetPath:(UIBezierPath*)path by:(CGPoint)offset; |
||||||
|
|
||||||
|
#else |
||||||
|
+ (NSBezierPath*)offsetPath:(NSBezierPath*)path by:(CGPoint)offset; |
||||||
|
|
||||||
|
#endif |
||||||
|
@end |
||||||
|
|
||||||
|
#if (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE) |
||||||
|
#else |
||||||
|
@interface NSBezierPath (Path) |
||||||
|
- (CGPathRef)quartzPath; |
||||||
|
@end |
||||||
|
|
||||||
|
@interface NSImage (cgImage) |
||||||
|
-(CGImageRef)cgImage; |
||||||
|
@end |
||||||
|
|
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,346 @@ |
|||||||
|
// |
||||||
|
// QCMethod.m |
||||||
|
// |
||||||
|
// www.quartzcodeapp.com |
||||||
|
// |
||||||
|
|
||||||
|
#import "QCMethod.h" |
||||||
|
|
||||||
|
@implementation QCMethod |
||||||
|
|
||||||
|
+ (CAAnimation*)reverseAnimation:(CAAnimation*)anim totalDuration:(CGFloat)totalDuration{ |
||||||
|
CGFloat duration = anim.duration + (anim.autoreverses ? anim.duration : 0); |
||||||
|
duration = anim.repeatCount > 1 ? duration * anim.repeatCount : duration; |
||||||
|
|
||||||
|
CGFloat endTime = anim.beginTime + duration; |
||||||
|
CGFloat reverseStartTime = totalDuration - endTime; |
||||||
|
|
||||||
|
CAAnimation *newAnim; |
||||||
|
//Reverse timing function |
||||||
|
void (^reverseTimingFunction)(CAAnimation*) = ^(CAAnimation *theAnim){ |
||||||
|
CAMediaTimingFunction *timingFunction = theAnim.timingFunction; |
||||||
|
if (timingFunction) { |
||||||
|
float first[2]; |
||||||
|
float second[2]; |
||||||
|
[timingFunction getControlPointAtIndex:1 values:first]; |
||||||
|
[timingFunction getControlPointAtIndex:2 values:second]; |
||||||
|
theAnim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:1-second[0] :1-second[1] :1-first[0] :1-first[1]]; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Reverse animation values appropriately |
||||||
|
if ([anim isKindOfClass:[CABasicAnimation class]]) { |
||||||
|
CABasicAnimation *basicAnim = (CABasicAnimation*)anim; |
||||||
|
|
||||||
|
if (!anim.autoreverses) { |
||||||
|
id fromValue = basicAnim.toValue; |
||||||
|
basicAnim.toValue = basicAnim.fromValue; |
||||||
|
basicAnim.fromValue = fromValue; |
||||||
|
reverseTimingFunction(basicAnim); |
||||||
|
} |
||||||
|
basicAnim.beginTime = reverseStartTime; |
||||||
|
|
||||||
|
if (reverseStartTime > 0) { |
||||||
|
CAAnimationGroup *groupAnim = [CAAnimationGroup animation]; |
||||||
|
groupAnim.animations = @[basicAnim]; |
||||||
|
groupAnim.duration = [self maxDurationFromAnimations:groupAnim.animations]; |
||||||
|
[groupAnim.animations setValue:kCAFillModeBoth forKeyPath:@"fillMode"]; |
||||||
|
newAnim = groupAnim; |
||||||
|
}else newAnim = basicAnim; |
||||||
|
} |
||||||
|
else if ([anim isKindOfClass:[CAKeyframeAnimation class]]) { |
||||||
|
CAKeyframeAnimation *keyAnim = (CAKeyframeAnimation*)anim; |
||||||
|
|
||||||
|
if (!anim.autoreverses) { |
||||||
|
NSArray *values = [[keyAnim.values reverseObjectEnumerator] allObjects]; |
||||||
|
keyAnim.values = values; |
||||||
|
reverseTimingFunction(keyAnim); |
||||||
|
} |
||||||
|
keyAnim.beginTime = reverseStartTime; |
||||||
|
|
||||||
|
if (reverseStartTime > 0) { |
||||||
|
CAAnimationGroup *groupAnim = [CAAnimationGroup animation]; |
||||||
|
groupAnim.animations = @[keyAnim]; |
||||||
|
groupAnim.duration = [self maxDurationFromAnimations:groupAnim.animations]; |
||||||
|
[groupAnim.animations setValue:kCAFillModeBoth forKeyPath:@"fillMode"]; |
||||||
|
newAnim = groupAnim; |
||||||
|
}else newAnim = keyAnim; |
||||||
|
|
||||||
|
} |
||||||
|
else if ([anim isKindOfClass:[CAAnimationGroup class]]) { |
||||||
|
CAAnimationGroup *groupAnim = (CAAnimationGroup*)anim; |
||||||
|
NSMutableArray *newSubAnims = [NSMutableArray arrayWithCapacity:groupAnim.animations.count]; |
||||||
|
for (CAAnimation *subAnim in groupAnim.animations) { |
||||||
|
CAAnimation *newSubAnim = [self reverseAnimation:subAnim totalDuration:totalDuration]; |
||||||
|
[newSubAnims addObject:newSubAnim]; |
||||||
|
} |
||||||
|
groupAnim.animations = newSubAnims; |
||||||
|
[groupAnim.animations setValue:kCAFillModeBoth forKeyPath:@"fillMode"]; |
||||||
|
groupAnim.duration = [self maxDurationFromAnimations:newSubAnims]; |
||||||
|
newAnim = groupAnim; |
||||||
|
}else newAnim = anim; |
||||||
|
|
||||||
|
return newAnim; |
||||||
|
} |
||||||
|
|
||||||
|
+ (CAAnimationGroup*)groupAnimations:(NSArray*)animations fillMode:(NSString*)fillMode forEffectLayer:(BOOL)forEffectLayer sublayersCount:(NSInteger)count{ |
||||||
|
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; |
||||||
|
groupAnimation.animations = animations; |
||||||
|
if (fillMode) { |
||||||
|
[groupAnimation.animations setValue:fillMode forKeyPath:@"fillMode"]; |
||||||
|
groupAnimation.fillMode = fillMode; |
||||||
|
groupAnimation.removedOnCompletion = NO; |
||||||
|
} |
||||||
|
|
||||||
|
if (forEffectLayer) { |
||||||
|
groupAnimation.duration = [QCMethod maxDurationOfEffectAnimation:groupAnimation sublayersCount:count]; |
||||||
|
}else{ |
||||||
|
groupAnimation.duration = [QCMethod maxDurationFromAnimations:animations]; |
||||||
|
} |
||||||
|
return groupAnimation; |
||||||
|
} |
||||||
|
|
||||||
|
+ (CAAnimationGroup*)groupAnimations:(NSArray*)animations fillMode:(NSString*)fillMode{ |
||||||
|
return [self groupAnimations:animations fillMode:fillMode forEffectLayer:NO sublayersCount:0]; |
||||||
|
} |
||||||
|
+ (CGFloat)maxDurationFromAnimations:(NSArray*)anims{ |
||||||
|
CGFloat maxDuration = 0; |
||||||
|
for (CAAnimation *anim in anims) { |
||||||
|
maxDuration = MAX(anim.beginTime + anim.duration * (CGFloat)(anim.repeatCount == 0 ? 1.0f : anim.repeatCount) * (anim.autoreverses ? 2.0f : 1.0f), maxDuration); |
||||||
|
} |
||||||
|
if (maxDuration == INFINITY) { |
||||||
|
maxDuration = 1000.0f; |
||||||
|
} |
||||||
|
|
||||||
|
return maxDuration; |
||||||
|
} |
||||||
|
|
||||||
|
+ (CGFloat)maxDurationOfEffectAnimation:(CAAnimationGroup*)anim sublayersCount:(NSInteger)count{ |
||||||
|
CGFloat maxDuration = 0; |
||||||
|
if ([anim isKindOfClass:[CAAnimationGroup class]]) { |
||||||
|
for (CABasicAnimation *subAnim in anim.animations) { |
||||||
|
CGFloat instanceDelay = [[subAnim valueForKey:@"instanceDelay"] floatValue]; |
||||||
|
CGFloat delay = instanceDelay * (CGFloat)(count - 1); |
||||||
|
CGFloat repeatCountDuration = 0; |
||||||
|
if (subAnim.repeatCount >1) { |
||||||
|
repeatCountDuration = (subAnim.duration * (subAnim.repeatCount-1)); |
||||||
|
} |
||||||
|
|
||||||
|
CGFloat duration = subAnim.beginTime + (subAnim.autoreverses ? subAnim.duration : 0) + (delay + subAnim.duration + repeatCountDuration); |
||||||
|
maxDuration = MAX(duration, maxDuration); |
||||||
|
} |
||||||
|
} |
||||||
|
if (maxDuration == INFINITY) { |
||||||
|
maxDuration = 1000.0f; |
||||||
|
} |
||||||
|
return maxDuration; |
||||||
|
} |
||||||
|
|
||||||
|
+ (void)updateValueFromAnimationsForLayers:(NSArray*)layers{ |
||||||
|
[CATransaction begin]; |
||||||
|
[CATransaction setDisableActions:YES]; |
||||||
|
|
||||||
|
for (CALayer *layer in layers) { |
||||||
|
for (NSString *animKey in layer.animationKeys) { |
||||||
|
CAAnimation *anim = [layer animationForKey:animKey]; |
||||||
|
[self updateValueForAnimation:anim theLayer:layer]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[CATransaction commit]; |
||||||
|
} |
||||||
|
|
||||||
|
+ (void)updateValueForAnimation:(CAAnimation*)anim theLayer:(CALayer *)layer{ |
||||||
|
if ([anim isKindOfClass:[CABasicAnimation class]]) { |
||||||
|
CABasicAnimation *basicAnim = (CABasicAnimation*)anim; |
||||||
|
if (!basicAnim.autoreverses) { |
||||||
|
[layer setValue:basicAnim.toValue forKeyPath:basicAnim.keyPath]; |
||||||
|
} |
||||||
|
} |
||||||
|
else if ([anim isKindOfClass:[CAKeyframeAnimation class]]) { |
||||||
|
CAKeyframeAnimation *keyAnim = (CAKeyframeAnimation*)anim; |
||||||
|
if (!anim.autoreverses) { |
||||||
|
[layer setValue:keyAnim.values.lastObject forKeyPath:keyAnim.keyPath]; |
||||||
|
} |
||||||
|
} |
||||||
|
else if ([anim isKindOfClass:[CAAnimationGroup class]]) { |
||||||
|
CAAnimationGroup *groupAnim = (CAAnimationGroup*)anim; |
||||||
|
for (CAAnimation *subAnim in groupAnim.animations) { |
||||||
|
[self updateValueForAnimation:subAnim theLayer:layer]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
+ (void)updateValueFromPresentationLayerForAnimation:(CAAnimation*)anim theLayer:(CALayer *)layer{ |
||||||
|
if ([anim isKindOfClass:[CABasicAnimation class]] || [anim isKindOfClass:[CAKeyframeAnimation class]]) { |
||||||
|
CABasicAnimation *basicAnim = (CABasicAnimation*)anim; |
||||||
|
[layer setValue:[layer.presentationLayer valueForKeyPath:basicAnim.keyPath] forKeyPath:basicAnim.keyPath]; |
||||||
|
} |
||||||
|
else if ([anim isKindOfClass:[CAAnimationGroup class]]) { |
||||||
|
CAAnimationGroup *groupAnim = (CAAnimationGroup*)anim; |
||||||
|
for (CAAnimation *subAnim in groupAnim.animations) { |
||||||
|
[self updateValueFromPresentationLayerForAnimation:subAnim theLayer:layer]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
+ (void)addSublayersAnimation:(CAAnimation*)anim forKey:(NSString*)key forLayer:(CALayer*)layer{ |
||||||
|
[self addSublayersAnimationNeedReverse:anim forKey:key forLayer:layer reverseAnimation:NO totalDuration:0]; |
||||||
|
} |
||||||
|
|
||||||
|
//!Add animation to each sublayer in effect layer |
||||||
|
+ (void)addSublayersAnimationNeedReverse:(CAAnimation*)anim forKey:(NSString*)key forLayer:(CALayer*)layer reverseAnimation:(BOOL)reverse totalDuration:(CGFloat)totalDuration{ |
||||||
|
NSArray *sublayers = layer.sublayers; |
||||||
|
NSInteger sublayersCount = sublayers.count; |
||||||
|
|
||||||
|
void (^setBeginTime)(CAAnimation*, NSInteger) = ^(CAAnimation *subAnim, NSInteger sublayerIdx){ |
||||||
|
CGFloat instanceDelay = [[subAnim valueForKey:@"instanceDelay"] floatValue]; |
||||||
|
NSInteger orderType = [[subAnim valueForKey:@"instanceOrder"] integerValue]; |
||||||
|
switch (orderType) { |
||||||
|
case 0: subAnim.beginTime += sublayerIdx * instanceDelay; break; |
||||||
|
case 1: subAnim.beginTime += (sublayersCount - sublayerIdx - 1) * instanceDelay; break; |
||||||
|
case 2: { |
||||||
|
CGFloat middleIdx = sublayersCount/2.0f; |
||||||
|
CGFloat begin = fabs((middleIdx - sublayerIdx)) * instanceDelay ; |
||||||
|
subAnim.beginTime += begin; break; |
||||||
|
} |
||||||
|
case 3: { |
||||||
|
CGFloat middleIdx = sublayersCount/2.0f; |
||||||
|
CGFloat begin = (middleIdx - fabs((middleIdx - sublayerIdx))) * instanceDelay ; |
||||||
|
subAnim.beginTime += begin; break; |
||||||
|
} |
||||||
|
case 4: { |
||||||
|
//Add yours here |
||||||
|
} |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
[sublayers enumerateObjectsWithOptions:0 usingBlock:^(CALayer *sublayer, NSUInteger idx, BOOL *stop) { |
||||||
|
if ([anim isKindOfClass:[CAAnimationGroup class]]) { |
||||||
|
CAAnimationGroup *groupAnim = (CAAnimationGroup*)anim.copy; |
||||||
|
NSMutableArray *newSubAnimations = [NSMutableArray arrayWithCapacity:groupAnim.animations.count]; |
||||||
|
for (CABasicAnimation *subAnim in groupAnim.animations) { |
||||||
|
[newSubAnimations addObject:subAnim.copy]; |
||||||
|
} |
||||||
|
|
||||||
|
groupAnim.animations = newSubAnimations; |
||||||
|
NSArray *animations = [(CAAnimationGroup*)groupAnim animations]; |
||||||
|
for (CABasicAnimation *sub in animations) { |
||||||
|
setBeginTime(sub, idx); |
||||||
|
|
||||||
|
//Reverse animation if needed |
||||||
|
if (reverse) [self reverseAnimation:sub totalDuration:totalDuration]; |
||||||
|
} |
||||||
|
[sublayer addAnimation:groupAnim forKey:key]; |
||||||
|
} |
||||||
|
else{ |
||||||
|
CABasicAnimation *copiedAnim = anim.copy; |
||||||
|
setBeginTime(copiedAnim, idx); |
||||||
|
[sublayer addAnimation:copiedAnim forKey:key]; |
||||||
|
} |
||||||
|
}]; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#if (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE) |
||||||
|
+ (UIBezierPath*)alignToBottomPath:(UIBezierPath*)path layer:(CALayer*)layer{ |
||||||
|
CGFloat diff = CGRectGetMaxY(layer.bounds) - CGRectGetMaxY(path.bounds); |
||||||
|
CGAffineTransform affineTransform = CGAffineTransformTranslate(CGAffineTransformIdentity, 0, diff); |
||||||
|
[path applyTransform:affineTransform]; |
||||||
|
return path; |
||||||
|
} |
||||||
|
|
||||||
|
+ (UIBezierPath*)offsetPath:(UIBezierPath*)path by:(CGPoint)offset{ |
||||||
|
CGAffineTransform affineTransform = CGAffineTransformTranslate(CGAffineTransformIdentity, offset.x, offset.y); |
||||||
|
[path applyTransform:affineTransform]; |
||||||
|
return path; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#else |
||||||
|
+ (NSBezierPath*)offsetPath:(NSBezierPath*)path by:(CGPoint)offset{ |
||||||
|
NSAffineTransform* xfm = [NSAffineTransform transform]; |
||||||
|
[xfm translateXBy:offset.x yBy:offset.y]; |
||||||
|
[path transformUsingAffineTransform:xfm]; |
||||||
|
return path; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
@end |
||||||
|
|
||||||
|
|
||||||
|
#if (TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE) |
||||||
|
#else |
||||||
|
@implementation NSBezierPath (Path) |
||||||
|
|
||||||
|
- (CGPathRef)quartzPath{ |
||||||
|
NSInteger i, numElements; |
||||||
|
CGPathRef immutablePath = NULL; |
||||||
|
numElements = [self elementCount]; |
||||||
|
|
||||||
|
if (numElements > 0) |
||||||
|
{ |
||||||
|
CGMutablePathRef path = CGPathCreateMutable(); |
||||||
|
NSPoint points[3]; |
||||||
|
BOOL didClosePath = YES; |
||||||
|
|
||||||
|
for (i = 0; i < numElements; i++) |
||||||
|
{ |
||||||
|
switch ([self elementAtIndex:i associatedPoints:points]) |
||||||
|
{ |
||||||
|
case NSMoveToBezierPathElement: |
||||||
|
CGPathMoveToPoint(path, NULL, points[0].x, points[0].y); |
||||||
|
break; |
||||||
|
|
||||||
|
case NSLineToBezierPathElement: |
||||||
|
CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y); |
||||||
|
didClosePath = NO; |
||||||
|
break; |
||||||
|
|
||||||
|
case NSCurveToBezierPathElement: |
||||||
|
CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y, |
||||||
|
points[1].x, points[1].y, |
||||||
|
points[2].x, points[2].y); |
||||||
|
didClosePath = NO; |
||||||
|
break; |
||||||
|
|
||||||
|
case NSClosePathBezierPathElement: |
||||||
|
CGPathCloseSubpath(path); |
||||||
|
didClosePath = YES; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!didClosePath){ |
||||||
|
//CGPathCloseSubpath(path); |
||||||
|
} |
||||||
|
|
||||||
|
immutablePath = CGPathCreateCopy(path); |
||||||
|
CGPathRelease(path); |
||||||
|
} |
||||||
|
return immutablePath; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
||||||
|
|
||||||
|
@implementation NSImage (cgImage) |
||||||
|
|
||||||
|
-(CGImageRef)cgImage{ |
||||||
|
NSData* data = [self TIFFRepresentation]; |
||||||
|
CGImageRef imageRef = NULL; |
||||||
|
CGImageSourceRef sourceRef; |
||||||
|
|
||||||
|
sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); |
||||||
|
if(sourceRef) { |
||||||
|
imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL); |
||||||
|
CFRelease(sourceRef); |
||||||
|
} |
||||||
|
return imageRef; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "HongKong.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "LA.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 197 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "NYC.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 162 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "Paris.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "SF.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 7.2 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "Singapore.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 216 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "Tokyo.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "london.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 46 KiB |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"images" : [ |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"filename" : "sydney.jpg", |
||||||
|
"scale" : "1x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "2x" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"idiom" : "universal", |
||||||
|
"scale" : "3x" |
||||||
|
} |
||||||
|
], |
||||||
|
"info" : { |
||||||
|
"version" : 1, |
||||||
|
"author" : "xcode" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 56 KiB |