Commit 542797fb by Daniel Dahan

development: renamed Pulse to MotionPulse and added MotionSpring

parent 23bd140d
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
961730361E0E156400A9A297 /* MotionSpring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961730351E0E156400A9A297 /* MotionSpring.swift */; };
9617B07D1DFCA8CF00410F8F /* Application.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961E6BDE1DDA2A95004E6C93 /* Application.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 9617B07D1DFCA8CF00410F8F /* Application.swift in Headers */ = {isa = PBXBuildFile; fileRef = 961E6BDE1DDA2A95004E6C93 /* Application.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9617B07E1DFCA8CF00410F8F /* Card.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB75D1CB40DC500C806FE /* Card.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 9617B07E1DFCA8CF00410F8F /* Card.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB75D1CB40DC500C806FE /* Card.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9617B07F1DFCA8CF00410F8F /* ImageCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7621CB40DC500C806FE /* ImageCard.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 9617B07F1DFCA8CF00410F8F /* ImageCard.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7621CB40DC500C806FE /* ImageCard.swift */; settings = {ATTRIBUTES = (Public, ); }; };
...@@ -228,6 +229,7 @@ ...@@ -228,6 +229,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
961276621DCD8B1800A7D920 /* CharacterAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CharacterAttribute.swift; sourceTree = "<group>"; }; 961276621DCD8B1800A7D920 /* CharacterAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CharacterAttribute.swift; sourceTree = "<group>"; };
961730351E0E156400A9A297 /* MotionSpring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionSpring.swift; sourceTree = "<group>"; };
961DED451DCC40C500F425B6 /* Editor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = "<group>"; }; 961DED451DCC40C500F425B6 /* Editor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = "<group>"; };
961DED4A1DCC546100F425B6 /* EditorController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorController.swift; sourceTree = "<group>"; }; 961DED4A1DCC546100F425B6 /* EditorController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorController.swift; sourceTree = "<group>"; };
961E6BDE1DDA2A95004E6C93 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; }; 961E6BDE1DDA2A95004E6C93 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
...@@ -793,6 +795,7 @@ ...@@ -793,6 +795,7 @@
96BCB77E1CB40DC500C806FE /* MotionKeyframe.swift */, 96BCB77E1CB40DC500C806FE /* MotionKeyframe.swift */,
96E3C39D1D3A1D0C0086A024 /* MotionBasic.swift */, 96E3C39D1D3A1D0C0086A024 /* MotionBasic.swift */,
96BCB7821CB40DC500C806FE /* MotionPulse.swift */, 96BCB7821CB40DC500C806FE /* MotionPulse.swift */,
961730351E0E156400A9A297 /* MotionSpring.swift */,
); );
name = Motion; name = Motion;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1161,6 +1164,7 @@ ...@@ -1161,6 +1164,7 @@
965E81031DD4D5C800D61E4B /* CollectionView.swift in Sources */, 965E81031DD4D5C800D61E4B /* CollectionView.swift in Sources */,
965E81041DD4D5C800D61E4B /* CollectionViewCell.swift in Sources */, 965E81041DD4D5C800D61E4B /* CollectionViewCell.swift in Sources */,
965E81071DD4D5C800D61E4B /* CollectionViewLayout.swift in Sources */, 965E81071DD4D5C800D61E4B /* CollectionViewLayout.swift in Sources */,
961730361E0E156400A9A297 /* MotionSpring.swift in Sources */,
965E81081DD4D5C800D61E4B /* CollectionReusableView.swift in Sources */, 965E81081DD4D5C800D61E4B /* CollectionReusableView.swift in Sources */,
965E81091DD4D5C800D61E4B /* DataSourceItem.swift in Sources */, 965E81091DD4D5C800D61E4B /* DataSourceItem.swift in Sources */,
965E810A1DD4D5C800D61E4B /* Font.swift in Sources */, 965E810A1DD4D5C800D61E4B /* Font.swift in Sources */,
......
...@@ -40,7 +40,7 @@ open class Button: UIButton, Pulseable { ...@@ -40,7 +40,7 @@ open class Button: UIButton, Pulseable {
open let visualLayer = CAShapeLayer() open let visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
fileprivate var pulse: Pulse! fileprivate var pulse: MotionPulse!
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -261,7 +261,7 @@ extension Button { ...@@ -261,7 +261,7 @@ extension Button {
/// Prepares the pulse motion. /// Prepares the pulse motion.
fileprivate func preparePulse() { fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer) pulse = MotionPulse(pulseView: self, pulseLayer: visualLayer)
} }
/** /**
......
...@@ -41,7 +41,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -41,7 +41,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
open let visualLayer = CAShapeLayer() open let visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
fileprivate var pulse: Pulse! fileprivate var pulse: MotionPulse!
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -295,7 +295,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -295,7 +295,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
extension CollectionReusableView { extension CollectionReusableView {
/// Prepares the pulse motion. /// Prepares the pulse motion.
fileprivate func preparePulse() { fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer) pulse = MotionPulse(pulseView: self, pulseLayer: visualLayer)
pulseAnimation = .none pulseAnimation = .none
} }
......
...@@ -41,7 +41,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -41,7 +41,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
open let visualLayer = CAShapeLayer() open let visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
fileprivate var pulse: Pulse! fileprivate var pulse: MotionPulse!
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -256,7 +256,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -256,7 +256,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
extension CollectionViewCell { extension CollectionViewCell {
/// Prepares the pulse motion. /// Prepares the pulse motion.
fileprivate func preparePulse() { fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer) pulse = MotionPulse(pulseView: self, pulseLayer: visualLayer)
} }
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
......
...@@ -30,8 +30,16 @@ ...@@ -30,8 +30,16 @@
import UIKit import UIKit
@objc(FABMenuDirection)
public enum FABMenuDirection: Int {
case up
case down
case left
case right
}
@objc(FABMenuDelegate) @objc(FABMenuDelegate)
public protocol FABMenuDelegate: MenuDelegate { public protocol FABMenuDelegate {
/** /**
Gets called when the user taps while the menu is opened. Gets called when the user taps while the menu is opened.
- Parameter menu: A FABMenu. - Parameter menu: A FABMenu.
...@@ -46,6 +54,16 @@ public protocol FABMenuDelegate: MenuDelegate { ...@@ -46,6 +54,16 @@ public protocol FABMenuDelegate: MenuDelegate {
@objc(FABMenu) @objc(FABMenu)
open class FABMenu: Menu { open class FABMenu: Menu {
/// An optional delegation handler.
open weak var delegate: FABMenuDelegate?
/// The direction in which the animation opens the menu.
open var direction = SpringDirection.up {
didSet {
layoutSubviews()
}
}
/// A reference to the MenuItems /// A reference to the MenuItems
open var buttons: [MenuItem] { open var buttons: [MenuItem] {
get { get {
...@@ -55,8 +73,30 @@ open class FABMenu: Menu { ...@@ -55,8 +73,30 @@ open class FABMenu: Menu {
views = value views = value
} }
} }
}
open override func prepare() {
super.prepare() extension FABMenu {
/**
Handles the hit test for the Menu and views outside of the Menu bounds.
- Parameter _ point: A CGPoint.
- Parameter with event: An optional UIEvent.
- Returns: An optional UIView.
*/
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isOpened, isEnabled else {
return super.hitTest(point, with: event)
}
for v in subviews {
let p = v.convert(point, from: self)
if v.bounds.contains(p) {
delegate?.fabMenu?(fabMenu: self, tappedAt: point, isOutside: false)
return v.hitTest(p, with: event)
}
}
delegate?.fabMenu?(fabMenu: self, tappedAt: point, isOutside: true)
return self.hitTest(point, with: event)
} }
} }
...@@ -30,584 +30,18 @@ ...@@ -30,584 +30,18 @@
import UIKit import UIKit
@objc(MenuDirection) @objc(menu)
public enum MenuDirection: Int { open class Menu: View, Springable {
case up internal let spring = Spring()
case down
case left
case right
}
@objc(MenuDelegate)
public protocol MenuDelegate {
/**
Gets called when the user taps while the menu is opened.
- Parameter menu: A Menu.
- Parameter tappedAt point: A CGPoint.
- Parameter isOutside: A boolean indicating whether the tap
was outside the menu button area.
*/
@objc
optional func menu(menu: Menu, tappedAt point: CGPoint, isOutside: Bool)
}
open class Menu: View {
/// A Boolean that indicates if the menu is open or not.
open internal(set) var isOpened = false
/// Enables the animations for the Menu.
open internal(set) var isEnabled = true
/// A preset wrapper around interimSpace. open var views: [UIView] {
open var interimSpacePreset = InterimSpacePreset.none { get {
didSet { return spring.views
interimSpace = InterimSpacePresetToValue(preset: interimSpacePreset)
} }
} set(value) {
spring.views = value
/// The space between views.
open var interimSpace: InterimSpace = 0 {
didSet {
layoutSubviews()
}
}
/// The direction in which the animation opens the menu.
open var direction = MenuDirection.up {
didSet {
layoutSubviews()
} }
} }
/// A delegation reference. open var springDirection = SpringDirection.up
open weak var delegate: MenuDelegate?
/// An Array of UIViews.
open var views = [UIView]() {
didSet {
for v in oldValue {
v.removeFromSuperview()
}
for v in views {
addSubview(v)
}
layoutSubviews()
}
}
/// An Optional base view size.
open var baseSize = CGSize(width: 48, height: 48)
/// Size of views, not including the first view.
open var itemSize = CGSize(width: 48, height: 48)
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isOpened, isEnabled else {
return super.hitTest(point, with: event)
}
for v in subviews {
let p = v.convert(point, from: self)
if v.bounds.contains(p) {
delegate?.menu?(menu: self, tappedAt: point, isOutside: false)
return v.hitTest(p, with: event)
}
}
delegate?.menu?(menu: self, tappedAt: point, isOutside: true)
return self.hitTest(point, with: event)
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
to initialize property values and other setup operations.
The super.prepare method should always be called immediately
when subclassing.
*/
open override func prepare() {
super.prepare()
backgroundColor = nil
interimSpacePreset = .interimSpace6
}
open override func layoutSubviews() {
super.layoutSubviews()
reload()
}
/// Reload the view layout.
open func reload() {
isOpened = false
guard let base = views.first else {
return
}
base.frame.size = baseSize
base.zPosition = 10000
for i in 1..<views.count {
let v = views[i]
v.alpha = 0
v.isHidden = true
v.frame.size = itemSize
v.x = base.x + (baseSize.width - itemSize.width) / 2
v.y = base.y + (baseSize.height - itemSize.height) / 2
v.zPosition = CGFloat(10000 - views.count - i)
}
}
/// Disable the Menu if views exist.
fileprivate func disable() {
guard 0 < views.count else {
return
}
isEnabled = false
}
/**
Enable the Menu if the last view is equal to the passed in view.
- Parameter view: UIView that is passed in to compare.
*/
fileprivate func enable(view: UIView) {
guard view == views.last else {
return
}
isEnabled = true
}
}
extension Menu {
/**
Open the Menu component with animation options.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
open func open(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
if isEnabled {
disable()
switch direction {
case .up:
openUpAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .down:
openDownAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .left:
openLeftAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .right:
openRightAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
}
}
/**
Close the Menu component with animation options.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
open func close(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
if isEnabled {
disable()
switch direction {
case .up:
closeUpAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .down:
closeDownAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .left:
closeLeftAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .right:
closeRightAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
}
}
}
extension Menu {
/**
Open the Menu component with animation options in the Up direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openUpAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
for i in 1..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [weak self, base = base, v = v] in
guard let s = self else {
return
}
v.alpha = 1
v.y = base.y - CGFloat(i) * s.itemSize.height - CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
guard let s = self else {
return
}
s.enable(view: v)
if v == s.views.last {
s.isOpened = true
}
completion?(v)
}
}
}
/**
Close the Menu component with animation options in the Up direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeUpAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
for i in 1..<views.count {
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [base = base, v = views[i]] in
v.alpha = 0
v.y = base.y
animations?(v)
}) { [weak self, v = views[i]] _ in
guard let s = self else {
return
}
v.isHidden = true
s.enable(view: v)
if v == s.views.last {
s.isOpened = false
}
completion?(v)
}
}
}
/**
Open the Menu component with animation options in the Down direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openDownAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
let h = baseSize.height
for i in 1..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [weak self, base = base, v = v] in
guard let s = self else {
return
}
v.alpha = 1
v.y = base.y + h + CGFloat(i - 1) * s.itemSize.height + CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
guard let s = self else {
return
}
s.enable(view: v)
if v == s.views.last {
s.isOpened = true
}
completion?(v)
}
}
}
/**
Close the Menu component with animation options in the Down direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeDownAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
let h = baseSize.height
for i in 1..<views.count {
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [base = base, v = views[i]] in
v.alpha = 0
v.y = base.y + h
animations?(v)
}) { [weak self, v = views[i]] _ in
guard let s = self else {
return
}
v.isHidden = true
s.enable(view: v)
if v == s.views.last {
s.isOpened = false
}
completion?(v)
}
}
}
/**
Open the Menu component with animation options in the Left direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openLeftAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
for i in 1..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [weak self, base = base, v = v] in
guard let s = self else {
return
}
v.alpha = 1
v.x = base.x - CGFloat(i) * s.itemSize.width - CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
guard let s = self else {
return
}
s.enable(view: v)
if v == s.views.last {
s.isOpened = true
}
completion?(v)
}
}
}
/**
Close the Menu component with animation options in the Left direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeLeftAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
for i in 1..<views.count {
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [v = views[i]] in
v.alpha = 0
v.x = base.x
animations?(v)
}) { [weak self, v = views[i]] _ in
guard let s = self else {
return
}
v.isHidden = true
s.enable(view: v)
if v == s.views.last {
s.isOpened = false
}
completion?(v)
}
}
}
/**
Open the Menu component with animation options in the Right direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openRightAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
let h = baseSize.height
for i in 1..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [weak self, base = base, v = v] in
guard let s = self else {
return
}
v.alpha = 1
v.x = base.x + h + CGFloat(i - 1) * s.itemSize.width + CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
guard let s = self else {
return
}
s.enable(view: v)
if v == s.views.last {
s.isOpened = true
}
completion?(v)
}
}
}
/**
Close the Menu component with animation options in the Right direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeRightAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let base = views.first else {
return
}
let w = baseSize.width
for i in 1..<views.count {
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [base = base, v = views[i]] in
v.alpha = 0
v.x = base.x + w
animations?(v)
}) { [weak self, v = views[i]] _ in
guard let s = self else {
return
}
v.isHidden = true
s.enable(view: v)
if v == s.views.last {
s.isOpened = false
}
completion?(v)
}
}
}
} }
...@@ -53,7 +53,7 @@ public protocol Pulseable { ...@@ -53,7 +53,7 @@ public protocol Pulseable {
var pulseOpacity: CGFloat { get set } var pulseOpacity: CGFloat { get set }
} }
public struct Pulse { public struct MotionPulse {
/// A UIView that is Pulseable. /// A UIView that is Pulseable.
fileprivate weak var pulseView: UIView? fileprivate weak var pulseView: UIView?
...@@ -64,7 +64,7 @@ public struct Pulse { ...@@ -64,7 +64,7 @@ public struct Pulse {
fileprivate var layers = [CAShapeLayer]() fileprivate var layers = [CAShapeLayer]()
/// A reference to the PulseAnimation. /// A reference to the PulseAnimation.
public var animation = PulseAnimation.pointWithBacking public var animation = MotionPulseAnimation.pointWithBacking
/// A UIColor. /// A UIColor.
public var color = Color.grey.base public var color = Color.grey.base
...@@ -81,7 +81,9 @@ public struct Pulse { ...@@ -81,7 +81,9 @@ public struct Pulse {
self.pulseView = pulseView self.pulseView = pulseView
self.pulseLayer = pulseLayer self.pulseLayer = pulseLayer
} }
}
extension MotionPulse {
/** /**
Triggers the expanding animation. Triggers the expanding animation.
- Parameter point: A point to pulse from. - Parameter point: A point to pulse from.
...@@ -157,7 +159,9 @@ public struct Pulse { ...@@ -157,7 +159,9 @@ public struct Pulse {
bLayer.setValue(true, forKey: "animated") bLayer.setValue(true, forKey: "animated")
} }
} }
}
extension MotionPulse {
/// Triggers the contracting animation. /// Triggers the contracting animation.
public mutating func contractAnimation() { public mutating func contractAnimation() {
guard let bLayer = layers.popLast() else { guard let bLayer = layers.popLast() else {
......
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
@objc(SpringDirection)
public enum SpringDirection: Int {
case up
case down
case left
case right
}
public protocol Springable {
/// A SpringDirection value.
var springDirection: SpringDirection { get set }
}
open class MotionSpring {
/// A SpringDirection value.
open var direction = SpringDirection.up
/// A Boolean that indicates if the menu is open or not.
open internal(set) var isOpened = false
/// Enables the animations for the Menu.
open internal(set) var isEnabled = true
/// A preset wrapper around interimSpace.
open var interimSpacePreset = InterimSpacePreset.none {
didSet {
interimSpace = InterimSpacePresetToValue(preset: interimSpacePreset)
}
}
/// The space between views.
open var interimSpace: InterimSpace = 0 {
didSet {
reload()
}
}
/// An Array of UIViews.
open var views = [UIView]()
/// An Optional base view size.
open var baseSize = CGSize(width: 48, height: 48) {
didSet {
reload()
}
}
/// Size of views.
open var itemSize = CGSize(width: 48, height: 48) {
didSet {
reload()
}
}
/// Reload the view layout.
open func reload() {
isOpened = false
guard let first = views.first else {
return
}
first.frame.size = baseSize
first.zPosition = 10000
for i in 0..<views.count {
let v = views[i]
v.alpha = 0
v.isHidden = true
v.frame.size = itemSize
v.x = first.x + (baseSize.width - itemSize.width) / 2
v.y = first.y + (baseSize.height - itemSize.height) / 2
v.zPosition = CGFloat(10000 - views.count - i)
}
}
}
extension MotionSpring {
/// Disable the Menu if views exist.
fileprivate func disable() {
guard 0 < views.count else {
return
}
isEnabled = false
}
/**
Enable the Menu if the last view is equal to the passed in view.
- Parameter view: UIView that is passed in to compare.
*/
fileprivate func enable(view: UIView) {
guard view == views.last else {
return
}
isEnabled = true
}
}
extension MotionSpring {
/**
Open the Menu component with animation options.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
open func open(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
guard isEnabled else {
return
}
disable()
switch direction {
case .up:
openUpAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .down:
openDownAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .left:
openLeftAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .right:
openRightAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
}
/**
Close the Menu component with animation options.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
open func close(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
guard isEnabled else {
return
}
disable()
switch direction {
case .up:
closeUpAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .down:
closeDownAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .left:
closeLeftAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
case .right:
closeRightAnimation(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
}
}
extension MotionSpring {
/**
Handles the animation open completion.
- Parameter view: A UIView.
- Parameter completion: A completion handler.
*/
fileprivate func handleOpenCompletion(view: UIView, completion: ((UIView) -> Void)?) {
enable(view: view)
if view == views.last {
isOpened = true
}
completion?(view)
}
/**
Handles the animation close completion.
- Parameter view: A UIView.
- Parameter completion: A completion handler.
*/
fileprivate func handleCloseCompletion(view: UIView, completion: ((UIView) -> Void)?) {
view.isHidden = true
enable(view: view)
if view == views.last {
isOpened = false
}
completion?(view)
}
}
extension MotionSpring {
/**
Open the Menu component with animation options in the Up direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openUpAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
for i in 0..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [s = self, first = first, v = v] in
v.alpha = 1
v.y = first.y - CGFloat(i) * v.height - CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
self?.handleOpenCompletion(view: v, completion: completion)
}
}
}
/**
Close the Menu component with animation options in the Up direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeUpAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
for i in 0..<views.count {
let v = views[i]
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [base = first, v = v] in
v.alpha = 0
v.y = base.y
animations?(v)
}) { [weak self, v = v] _ in
self?.handleCloseCompletion(view: v, completion: completion)
}
}
}
/**
Open the Menu component with animation options in the Down direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openDownAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
let h = baseSize.height
for i in 0..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [s = self, first = first, v = v] in
v.alpha = 1
v.y = first.y + h + CGFloat(i - 1) * s.itemSize.height + CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
self?.handleOpenCompletion(view: v, completion: completion)
}
}
}
/**
Close the Menu component with animation options in the Down direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeDownAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
let h = baseSize.height
for i in 0..<views.count {
let v = views[i]
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [first = first, v = v] in
v.alpha = 0
v.y = first.y + h
animations?(v)
}) { [weak self, v = v] _ in
self?.handleCloseCompletion(view: v, completion: completion)
}
}
}
/**
Open the Menu component with animation options in the Left direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openLeftAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
for i in 0..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [s = self, first = first, v = v] in
v.alpha = 1
v.x = first.x - CGFloat(i) * s.itemSize.width - CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
self?.handleOpenCompletion(view: v, completion: completion)
}
}
}
/**
Close the Menu component with animation options in the Left direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeLeftAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
for i in 0..<views.count {
let v = views[i]
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [first = first, v = v] in
v.alpha = 0
v.x = first.x
animations?(v)
}) { [weak self, v = v] _ in
self?.handleCloseCompletion(view: v, completion: completion)
}
}
}
/**
Open the Menu component with animation options in the Right direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func openRightAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
let h = baseSize.height
for i in 0..<views.count {
let v = views[i]
v.isHidden = false
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [s = self, first = first, v = v] in
v.alpha = 1
v.x = first.x + h + CGFloat(i - 1) * s.itemSize.width + CGFloat(i) * s.interimSpace
animations?(v)
}) { [weak self, v = v] _ in
self?.handleOpenCompletion(view: v, completion: completion)
}
}
}
/**
Close the Menu component with animation options in the Right direction.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
fileprivate func closeRightAnimation(duration: TimeInterval, delay: TimeInterval, usingSpringWithDamping: CGFloat, initialSpringVelocity: CGFloat, options: UIViewAnimationOptions, animations: ((UIView) -> Void)?, completion: ((UIView) -> Void)?) {
guard let first = views.first else {
return
}
let w = baseSize.width
for i in 0..<views.count {
let v = views[i]
UIView.animate(withDuration: Double(i) * duration,
delay: delay,
usingSpringWithDamping: usingSpringWithDamping,
initialSpringVelocity: initialSpringVelocity,
options: options,
animations: { [first = first, v = v] in
v.alpha = 0
v.x = first.x + w
animations?(v)
}) { [weak self, v = v] _ in
self?.handleCloseCompletion(view: v, completion: completion)
}
}
}
}
...@@ -32,7 +32,7 @@ import UIKit ...@@ -32,7 +32,7 @@ import UIKit
open class PulseView: View, Pulseable { open class PulseView: View, Pulseable {
/// A Pulse reference. /// A Pulse reference.
fileprivate var pulse: Pulse! fileprivate var pulse: MotionPulse!
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -129,6 +129,6 @@ open class PulseView: View, Pulseable { ...@@ -129,6 +129,6 @@ open class PulseView: View, Pulseable {
extension PulseView { extension PulseView {
/// Prepares the pulse motion. /// Prepares the pulse motion.
fileprivate func preparePulse() { fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer) pulse = MotionPulse(pulseView: self, pulseLayer: visualLayer)
} }
} }
...@@ -40,7 +40,7 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -40,7 +40,7 @@ open class TableViewCell: UITableViewCell, Pulseable {
open let visualLayer = CAShapeLayer() open let visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
fileprivate var pulse: Pulse! fileprivate var pulse: MotionPulse!
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -177,7 +177,7 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -177,7 +177,7 @@ open class TableViewCell: UITableViewCell, Pulseable {
extension TableViewCell { extension TableViewCell {
/// Prepares the pulse motion. /// Prepares the pulse motion.
fileprivate func preparePulse() { fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer) pulse = MotionPulse(pulseView: self, pulseLayer: visualLayer)
} }
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment