diff --git a/PulsingHalo.podspec b/PulsingHalo.podspec index 99173c3..47e3b5a 100644 --- a/PulsingHalo.podspec +++ b/PulsingHalo.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = "PulsingHalo" - s.version = "0.0.5" + s.version = "0.0.6" s.summary = "iOS Component For Creating A Pulsing Animation Great For Map Annotations And Beacons" s.homepage = "https://github.com/shu223/PulsingHalo" s.license = 'MIT' s.author = { "shu223" => "shuichi0526@gmail.com" } s.platform = :ios - s.source = { :git => "https://github.com/shu223/PulsingHalo.git", :tag => "0.0.5" } + s.source = { :git => "https://github.com/shu223/PulsingHalo.git", :tag => "0.0.6" } s.source_files = 'PulsingHalo/*.{h,m}' s.framework = 'QuartzCore' s.requires_arc = true diff --git a/PulsingHalo/PulsingHaloLayer.m b/PulsingHalo/PulsingHaloLayer.m index c6788eb..f18b0f7 100644 --- a/PulsingHalo/PulsingHaloLayer.m +++ b/PulsingHalo/PulsingHaloLayer.m @@ -62,6 +62,7 @@ - (instancetype)init { return [self initWithRepeatCount:INFINITY]; } + // ============================================================================= #pragma mark - Accessor @@ -109,8 +110,21 @@ - (void)setStartInterval:(NSTimeInterval)startInterval { self.instanceDelay = startInterval; } +- (void)setAnimationDuration:(NSTimeInterval)animationDuration { + + _animationDuration = animationDuration; + self.animationGroup.duration = animationDuration + self.pulseInterval; + for (CAAnimation *anAnimation in self.animationGroup.animations) { + anAnimation.duration = animationDuration; + } + [self.effect removeAllAnimations]; + [self.effect addAnimation:self.animationGroup forKey:@"pulse"]; + self.instanceDelay = (self.animationDuration + self.pulseInterval) / self.haloLayerNumber; +} + + // ============================================================================= -#pragma mark - private +#pragma mark - Private - (void)_setupProperties { _fromValueForRadius = 0.0; @@ -123,7 +137,7 @@ - (void)_setupProperties { self.radius = 60; self.haloLayerNumber = 1; self.startInterval = 1; - self.backgroundColor = [[UIColor colorWithRed:0.000 green:0.478 blue:1.000 alpha:1] CGColor]; + self.backgroundColor = [[UIColor colorWithRed:0.000 green:0.455 blue:0.756 alpha:1] CGColor]; } - (void)_setupAnimationGroup { diff --git a/PulsingHaloDemo.xcodeproj/project.pbxproj b/PulsingHaloDemo.xcodeproj/project.pbxproj index 7544e1f..50c4113 100644 --- a/PulsingHaloDemo.xcodeproj/project.pbxproj +++ b/PulsingHaloDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 8A76D79E1BD4CC6B00C3881D /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8A76D79D1BD4CC6B00C3881D /* Launch Screen.storyboard */; settings = {ASSET_TAGS = (); }; }; 8AC907151850659E00A74F2E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC907141850659E00A74F2E /* Foundation.framework */; }; 8AC907171850659E00A74F2E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC907161850659E00A74F2E /* CoreGraphics.framework */; }; 8AC907191850659E00A74F2E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AC907181850659E00A74F2E /* UIKit.framework */; }; @@ -35,6 +36,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 8A76D79D1BD4CC6B00C3881D /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; 8AC907111850659E00A74F2E /* PulsingHaloDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PulsingHaloDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8AC907141850659E00A74F2E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 8AC907161850659E00A74F2E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -116,13 +118,14 @@ 8AC9071A1850659E00A74F2E /* PulsingHaloDemo */ = { isa = PBXGroup; children = ( + 8AC9071B1850659E00A74F2E /* Supporting Files */, + 8AC9072C1850659E00A74F2E /* Images.xcassets */, + 8AC907261850659E00A74F2E /* Main.storyboard */, + 8A76D79D1BD4CC6B00C3881D /* Launch Screen.storyboard */, 8AC907231850659E00A74F2E /* AppDelegate.h */, 8AC907241850659E00A74F2E /* AppDelegate.m */, - 8AC907261850659E00A74F2E /* Main.storyboard */, 8AC907291850659E00A74F2E /* ViewController.h */, 8AC9072A1850659E00A74F2E /* ViewController.m */, - 8AC9072C1850659E00A74F2E /* Images.xcassets */, - 8AC9071B1850659E00A74F2E /* Supporting Files */, ); path = PulsingHaloDemo; sourceTree = ""; @@ -243,6 +246,7 @@ files = ( 8AC9072D1850659E00A74F2E /* Images.xcassets in Resources */, 8AC9071F1850659E00A74F2E /* InfoPlist.strings in Resources */, + 8A76D79E1BD4CC6B00C3881D /* Launch Screen.storyboard in Resources */, 8AC907281850659E00A74F2E /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -394,7 +398,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "PulsingHaloDemo/PulsingHaloDemo-Prefix.pch"; INFOPLIST_FILE = "PulsingHaloDemo/PulsingHaloDemo-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.4; PRODUCT_BUNDLE_IDENTIFIER = "Shuichi-Tsutsumi.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; @@ -409,7 +413,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "PulsingHaloDemo/PulsingHaloDemo-Prefix.pch"; INFOPLIST_FILE = "PulsingHaloDemo/PulsingHaloDemo-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.4; PRODUCT_BUNDLE_IDENTIFIER = "Shuichi-Tsutsumi.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; diff --git a/PulsingHaloDemo/Base.lproj/Main.storyboard b/PulsingHaloDemo/Base.lproj/Main.storyboard index 0c65359..afdf578 100644 --- a/PulsingHaloDemo/Base.lproj/Main.storyboard +++ b/PulsingHaloDemo/Base.lproj/Main.storyboard @@ -10,138 +10,245 @@ - - + + - - + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + - + + + diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Contents.json index a396706..7b28cc5 100644 --- a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,19 +1,40 @@ { "images" : [ { - "idiom" : "iphone", "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Small@2x.png", "scale" : "2x" }, { + "size" : "29x29", "idiom" : "iphone", + "filename" : "Icon-Small@3x.png", + "scale" : "3x" + }, + { "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-40@2x.png", "scale" : "2x" }, { + "size" : "40x40", "idiom" : "iphone", + "filename" : "Icon-40@3x.png", + "scale" : "3x" + }, + { "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" } ], "info" : { diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png new file mode 100644 index 0000000..ab185fa Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png new file mode 100644 index 0000000..cbbe4ac Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png new file mode 100644 index 0000000..cbbe4ac Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100644 index 0000000..600d555 Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png new file mode 100644 index 0000000..80fd09f Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png new file mode 100644 index 0000000..4a7090e Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/Contents.json b/PulsingHaloDemo/Images.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PulsingHaloDemo/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PulsingHaloDemo/Images.xcassets/Image.imageset/Contents.json b/PulsingHaloDemo/Images.xcassets/Image.imageset/Contents.json index 62d0ec8..a91e0f0 100644 --- a/PulsingHaloDemo/Images.xcassets/Image.imageset/Contents.json +++ b/PulsingHaloDemo/Images.xcassets/Image.imageset/Contents.json @@ -6,8 +6,12 @@ }, { "idiom" : "universal", - "scale" : "2x", - "filename" : "IPhone_5s.png" + "filename" : "IPhone_5s.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Contents.json b/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Contents.json index c79ebd3..8410c60 100644 --- a/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Contents.json +++ b/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -3,16 +3,18 @@ { "orientation" : "portrait", "idiom" : "iphone", + "filename" : "Default@2x.png", "extent" : "full-screen", "minimum-system-version" : "7.0", "scale" : "2x" }, { - "orientation" : "portrait", + "extent" : "full-screen", "idiom" : "iphone", "subtype" : "retina4", - "extent" : "full-screen", + "filename" : "Default-568h@2x.png", "minimum-system-version" : "7.0", + "orientation" : "portrait", "scale" : "2x" } ], diff --git a/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png new file mode 100644 index 0000000..2ef49ed Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Default@2x.png b/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 0000000..f4ea4ef Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/LaunchImage.launchimage/Default@2x.png differ diff --git a/PulsingHaloDemo/Images.xcassets/bluetooth_book.imageset/Contents.json b/PulsingHaloDemo/Images.xcassets/bluetooth_book.imageset/Contents.json new file mode 100644 index 0000000..e5549de --- /dev/null +++ b/PulsingHaloDemo/Images.xcassets/bluetooth_book.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bluetooth_book.pdf", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PulsingHaloDemo/Images.xcassets/bluetooth_book.imageset/bluetooth_book.pdf b/PulsingHaloDemo/Images.xcassets/bluetooth_book.imageset/bluetooth_book.pdf new file mode 100644 index 0000000..4b054d8 Binary files /dev/null and b/PulsingHaloDemo/Images.xcassets/bluetooth_book.imageset/bluetooth_book.pdf differ diff --git a/PulsingHaloDemo/Launch Screen.storyboard b/PulsingHaloDemo/Launch Screen.storyboard new file mode 100644 index 0000000..be1a8b5 --- /dev/null +++ b/PulsingHaloDemo/Launch Screen.storyboard @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PulsingHaloDemo/PulsingHaloDemo-Info.plist b/PulsingHaloDemo/PulsingHaloDemo-Info.plist index 6667e41..efef0bc 100644 --- a/PulsingHaloDemo/PulsingHaloDemo-Info.plist +++ b/PulsingHaloDemo/PulsingHaloDemo-Info.plist @@ -24,6 +24,8 @@ 1.0 LSRequiresIPhoneOS + UILaunchStoryboardName + Launch Screen UIMainStoryboardFile Main UIRequiredDeviceCapabilities @@ -33,8 +35,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight diff --git a/PulsingHaloDemo/ViewController.m b/PulsingHaloDemo/ViewController.m index a9672d4..dc507f5 100644 --- a/PulsingHaloDemo/ViewController.m +++ b/PulsingHaloDemo/ViewController.m @@ -10,21 +10,22 @@ #import "ViewController.h" #import "PulsingHaloLayer.h" -#define kMaxRadius 160 +#define kMaxRadius 200 +#define kMaxDuration 10 @interface ViewController () -@property (nonatomic, weak) PulsingHaloLayer *mutiHalo; @property (nonatomic, weak) PulsingHaloLayer *halo; @property (nonatomic, weak) IBOutlet UIImageView *beaconView; -@property (nonatomic, weak) IBOutlet UIImageView *beaconViewMuti; @property (nonatomic, weak) IBOutlet UISlider *countSlider; @property (nonatomic, weak) IBOutlet UISlider *radiusSlider; +@property (nonatomic, weak) IBOutlet UISlider *durationSlider; @property (nonatomic, weak) IBOutlet UISlider *rSlider; @property (nonatomic, weak) IBOutlet UISlider *gSlider; @property (nonatomic, weak) IBOutlet UISlider *bSlider; @property (nonatomic, weak) IBOutlet UILabel *countLabel; @property (nonatomic, weak) IBOutlet UILabel *radiusLabel; +@property (nonatomic, weak) IBOutlet UILabel *durationLabel; @property (nonatomic, weak) IBOutlet UILabel *rLabel; @property (nonatomic, weak) IBOutlet UILabel *gLabel; @property (nonatomic, weak) IBOutlet UILabel *bLabel; @@ -36,19 +37,11 @@ @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - - ///setup single halo layer + + // basic setup PulsingHaloLayer *layer = [PulsingHaloLayer layer]; self.halo = layer; - self.halo.position = self.beaconView.center; - [self.view.layer insertSublayer:self.halo below:self.beaconView.layer]; - - ///setup multiple halo layer - //you can specify the number of halos by initial method or by instance property "haloLayerNumber" - PulsingHaloLayer *multiLayer = [PulsingHaloLayer layer]; - self.mutiHalo = multiLayer; - self.mutiHalo.position = self.beaconViewMuti.center; - [self.view.layer insertSublayer:self.mutiHalo below:self.beaconViewMuti.layer]; + [self.beaconView.superview.layer insertSublayer:self.halo below:self.beaconView.layer]; [self setupInitialValues]; } @@ -59,21 +52,31 @@ - (void)didReceiveMemoryWarning // Dispose of any resources that can be recreated. } +- (void)viewDidLayoutSubviews +{ + [super viewDidLayoutSubviews]; + + self.halo.position = self.beaconView.center; +} + // ============================================================================= #pragma mark - Private - (void)setupInitialValues { - self.countSlider.value = 3; + self.countSlider.value = 5; [self countChanged:nil]; - self.radiusSlider.value = 0.5; + self.radiusSlider.value = 0.7; [self radiusChanged:nil]; - self.rSlider.value = 0; - self.gSlider.value = 0.487; - self.bSlider.value = 1.0; + self.durationSlider.value = 0.5; + [self durationChanged:nil]; + + self.rSlider.value = 0.; + self.gSlider.value = 0.455; + self.bSlider.value = 0.756; [self colorChanged:nil]; } @@ -83,17 +86,24 @@ - (void)setupInitialValues { - (IBAction)countChanged:(UISlider *)sender { + //you can specify the number of halos by initial method or by instance property "haloLayerNumber" float value = floor(self.countSlider.value); - self.mutiHalo.haloLayerNumber = value; + self.halo.haloLayerNumber = value; self.countLabel.text = [@(value) stringValue]; } - (IBAction)radiusChanged:(UISlider *)sender { - self.mutiHalo.radius = self.radiusSlider.value * kMaxRadius; self.halo.radius = self.radiusSlider.value * kMaxRadius; - self.radiusLabel.text = [@(self.radiusSlider.value) stringValue]; + self.radiusLabel.text = [NSString stringWithFormat:@"%.0f", self.radiusSlider.value * kMaxRadius]; +} + +- (IBAction)durationChanged:(UISlider *)sender { + + self.halo.animationDuration = self.durationSlider.value * kMaxDuration; + + self.durationLabel.text = [NSString stringWithFormat:@"%.1f", self.durationSlider.value * kMaxDuration]; } - (IBAction)colorChanged:(UISlider *)sender { @@ -103,12 +113,11 @@ - (IBAction)colorChanged:(UISlider *)sender { blue:self.bSlider.value alpha:1.0]; - [self.mutiHalo setBackgroundColor:color.CGColor]; [self.halo setBackgroundColor:color.CGColor]; - self.rLabel.text = [@(self.rSlider.value) stringValue]; - self.gLabel.text = [@(self.gSlider.value) stringValue]; - self.bLabel.text = [@(self.bSlider.value) stringValue]; + self.rLabel.text = [NSString stringWithFormat:@"%.2f", self.rSlider.value]; + self.gLabel.text = [NSString stringWithFormat:@"%.2f", self.gSlider.value]; + self.bLabel.text = [NSString stringWithFormat:@"%.2f", self.bSlider.value]; } @end diff --git a/README.md b/README.md index fed59e5..84d5b6e 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,56 @@ PulsingHalo =========== -iOS Component For Creating A Pulsing Animation. It allows you to create single halo or multiple halos. +iOS Component For Creating a Pulsing animation. It allows you to create halos. -![](http://f.cl.ly/items/2Q0X052p2m371m0w2O0C/halogif.gif "single halo | multiple halos") +![](demo.gif) Great For: -- **Beacons for iBeacon** +- **Pulses of beacons (iBeacon)** - Map Annotations ##How to use 1. Add PulsingHaloLayer.h,m into your project -2. Initiate and add to your view. +2. **Just initiate and add to your view layer**. -####Single halo ```` PulsingHaloLayer *halo = [PulsingHaloLayer layer]; halo.position = self.view.center; [self.view.layer addSublayer:halo]; ```` -####Multiple halos -```` -// initializer -PulsingHaloLayer *halo = [[PulsingHaloLayer alloc] initWithLayerNumber:3]; -halo.position = self.view.center; -[self.view.layer addSublayer:halo]; +###Install with CocoaPods -// property -PulsingHaloLayer *halo = [PulsingHaloLayer layer]; -halo.haloLayerNumber = 3; -halo.position = self.view.center; -[self.view.layer addSublayer:halo]; -```` - -##Install with CocoaPods - -Add Podfile. +Edit your Podfile. ```` pod "PulsingHalo" ```` -And - -```` -$ pod install -```` +And `$ pod install` ##Customization +###Number of Halos + +Use `haloLayerNumber` property. + +``` +halo.haloLayerNumber = 3; +``` + +Or you can use `initWithLayerNumber:`. + +```` +PulsingHaloLayer *halo = [[PulsingHaloLayer alloc] initWithLayerNumber:3]; +halo.position = self.view.center; +[self.view.layer addSublayer:halo]; +```` + ###radius Use `radius` property. @@ -96,8 +93,6 @@ Use property `useTimingFunction` You can try to change the radius and color properties with demo app. -![](http://f.cl.ly/items/0u3c211i2g372c390p44/halodemo.jpg) - ##Special Thanks diff --git a/demo.gif b/demo.gif new file mode 100644 index 0000000..c7fbce0 Binary files /dev/null and b/demo.gif differ