Commit 91591377 by Daniel Dahan

development: added Motion to Material

parent f5c3ef6c
......@@ -48,8 +48,6 @@
96328B9E1E05C24E009A4C90 /* TableView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96328B961E05C0BB009A4C90 /* TableView.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96328B9F1E05C24E009A4C90 /* TableViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96328B981E05C0CE009A4C90 /* TableViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96334EF61C8B84660083986B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96334EF51C8B84660083986B /* Assets.xcassets */; };
965E80C81DD4C50600D61E4B /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB76D1CB40DC500C806FE /* Animation.swift */; };
965E80CB1DD4C50600D61E4B /* BasicAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E3C39D1D3A1D0C0086A024 /* BasicAnimation.swift */; };
965E80CC1DD4C50600D61E4B /* Bar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7981CB40DC500C806FE /* Bar.swift */; };
965E80CD1DD4C50600D61E4B /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7701CB40DC500C806FE /* Button.swift */; };
965E80CE1DD4C50600D61E4B /* FABButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB75F1CB40DC500C806FE /* FABButton.swift */; };
......@@ -126,7 +124,6 @@
965E81241DD4D7C800D61E4B /* Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961DED451DCC40C500F425B6 /* Editor.swift */; };
965E81251DD4D7C800D61E4B /* EditorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961DED4A1DCC546100F425B6 /* EditorController.swift */; };
965E81261DD4D7C800D61E4B /* CharacterAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961276621DCD8B1800A7D920 /* CharacterAttribute.swift */; };
9697F7BC1D8F2572004741EC /* BasicAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96E3C39D1D3A1D0C0086A024 /* BasicAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9697F7BF1D8F2572004741EC /* Divider.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96230AB71D6A520C00AF47DC /* Divider.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9697F7C01D8F2572004741EC /* Material+CALayer.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96F1DC871D654FDF0025F925 /* Material+CALayer.swift */; settings = {ATTRIBUTES = (Public, ); }; };
9697F7C11D8F2572004741EC /* Material+Array.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96C1C8801D42C62800E6608F /* Material+Array.swift */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -142,7 +139,6 @@
96BCB7F71CB40DE900C806FE /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7F01CB40DE900C806FE /* Roboto-Medium.ttf */; };
96BCB7F91CB40DE900C806FE /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7F11CB40DE900C806FE /* Roboto-Regular.ttf */; };
96BCB7FB1CB40DE900C806FE /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 96BCB7F21CB40DE900C806FE /* Roboto-Thin.ttf */; };
96BCB8111CB4115200C806FE /* Animation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB76D1CB40DC500C806FE /* Animation.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8141CB4115200C806FE /* PulseAnimation.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7821CB40DC500C806FE /* PulseAnimation.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8151CB4115200C806FE /* FABButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB75F1CB40DC500C806FE /* FABButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8161CB4115200C806FE /* FlatButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7601CB40DC500C806FE /* FlatButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -188,6 +184,8 @@
96BCB8561CB4115200C806FE /* Switch.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7881CB40DC500C806FE /* Switch.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8571CB4115200C806FE /* View.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB78C1CB40DC500C806FE /* View.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BFC1541E5E486F0075DE1F /* SpringAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965532281E47E388005C2792 /* SpringAnimation.swift */; };
96BFC1681E61D9FD0075DE1F /* Motion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BFC1671E61D9FD0075DE1F /* Motion.swift */; };
96BFC16A1E61DAA10075DE1F /* MotionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BFC1691E61DAA10075DE1F /* MotionAnimation.swift */; };
96D88C321C1328D800B91418 /* Material.h in Headers */ = {isa = PBXBuildFile; fileRef = 96D88C091C1328D800B91418 /* Material.h */; settings = {ATTRIBUTES = (Public, ); }; };
96E3C3951D3A1CC20086A024 /* IconButton.swift in Headers */ = {isa = PBXBuildFile; fileRef = 9658F2161CD6FA4700B902C1 /* IconButton.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96E3C3961D3A1CC20086A024 /* CollectionReusableView.swift in Headers */ = {isa = PBXBuildFile; fileRef = 966ECF291CF4C20100BB0BDF /* CollectionReusableView.swift */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -246,7 +244,6 @@
96BCB7641CB40DC500C806FE /* Material+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+String.swift"; sourceTree = "<group>"; };
96BCB7651CB40DC500C806FE /* Material+UIFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIFont.swift"; sourceTree = "<group>"; };
96BCB76C1CB40DC500C806FE /* Material+UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage.swift"; sourceTree = "<group>"; };
96BCB76D1CB40DC500C806FE /* Animation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = "<group>"; };
96BCB76F1CB40DC500C806FE /* Border.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Border.swift; sourceTree = "<group>"; };
96BCB7701CB40DC500C806FE /* Button.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
96BCB7711CB40DC500C806FE /* CollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = "<group>"; };
......@@ -292,12 +289,13 @@
96BCB7F01CB40DE900C806FE /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = "<group>"; };
96BCB7F11CB40DE900C806FE /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
96BCB7F21CB40DE900C806FE /* Roboto-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Thin.ttf"; sourceTree = "<group>"; };
96BFC1671E61D9FD0075DE1F /* Motion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Motion.swift; sourceTree = "<group>"; };
96BFC1691E61DAA10075DE1F /* MotionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionAnimation.swift; sourceTree = "<group>"; };
96C1C8801D42C62800E6608F /* Material+Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+Array.swift"; sourceTree = "<group>"; };
96D88BFC1C1328D800B91418 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
96D88BFD1C1328D800B91418 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
96D88C091C1328D800B91418 /* Material.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Material.h; sourceTree = "<group>"; };
96E3C3931D397AE90086A024 /* Material+UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIView.swift"; sourceTree = "<group>"; };
96E3C39D1D3A1D0C0086A024 /* BasicAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicAnimation.swift; sourceTree = "<group>"; };
96F1DC871D654FDF0025F925 /* Material+CALayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+CALayer.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
......@@ -537,7 +535,6 @@
96BCB7571CB40DC500C806FE /* iOS */ = {
isa = PBXGroup;
children = (
96BCB8091CB4107700C806FE /* Animation */,
961E6BDD1DDA2A7E004E6C93 /* Application */,
96264BE41D833C8400576F37 /* Bar */,
9617306E1E16EFE300A9A297 /* BottomSheet */,
......@@ -559,6 +556,7 @@
96BCB80D1CB410FD00C806FE /* Layer */,
96BCB8041CB40F6C00C806FE /* Layout */,
963FBF021D6696D0008F8512 /* Menu */,
96BCB8091CB4107700C806FE /* Motion */,
96BCB8011CB40F1700C806FE /* Navigation */,
961E6BEF1DDA4B04004E6C93 /* NavigationDrawer */,
962DDD071D6FBBB7001C307C /* Page */,
......@@ -695,15 +693,15 @@
name = Icon;
sourceTree = "<group>";
};
96BCB8091CB4107700C806FE /* Animation */ = {
96BCB8091CB4107700C806FE /* Motion */ = {
isa = PBXGroup;
children = (
96BCB76D1CB40DC500C806FE /* Animation.swift */,
96E3C39D1D3A1D0C0086A024 /* BasicAnimation.swift */,
96BFC1671E61D9FD0075DE1F /* Motion.swift */,
96BFC1691E61DAA10075DE1F /* MotionAnimation.swift */,
96BCB7821CB40DC500C806FE /* PulseAnimation.swift */,
965532281E47E388005C2792 /* SpringAnimation.swift */,
);
name = Animation;
name = Motion;
sourceTree = "<group>";
};
96BCB80A1CB410A100C806FE /* Extension */ = {
......@@ -777,7 +775,6 @@
buildActionMask = 2147483647;
files = (
96D88C321C1328D800B91418 /* Material.h in Headers */,
96BCB8111CB4115200C806FE /* Animation.swift in Headers */,
96BCB8141CB4115200C806FE /* PulseAnimation.swift in Headers */,
96BCB8151CB4115200C806FE /* FABButton.swift in Headers */,
96BCB8161CB4115200C806FE /* FlatButton.swift in Headers */,
......@@ -828,7 +825,6 @@
96E3C3991D3A1CC20086A024 /* StatusBarController.swift in Headers */,
96E3C39A1D3A1CC20086A024 /* ErrorTextField.swift in Headers */,
96E3C39C1D3A1CC20086A024 /* Offset.swift in Headers */,
9697F7BC1D8F2572004741EC /* BasicAnimation.swift in Headers */,
9697F7BF1D8F2572004741EC /* Divider.swift in Headers */,
9697F7C01D8F2572004741EC /* Material+CALayer.swift in Headers */,
9697F7C11D8F2572004741EC /* Material+Array.swift in Headers */,
......@@ -961,6 +957,7 @@
965E81041DD4D5C800D61E4B /* CollectionViewCell.swift in Sources */,
965E81071DD4D5C800D61E4B /* CollectionViewLayout.swift in Sources */,
965E81081DD4D5C800D61E4B /* CollectionReusableView.swift in Sources */,
96BFC1681E61D9FD0075DE1F /* Motion.swift in Sources */,
965E81091DD4D5C800D61E4B /* DataSourceItem.swift in Sources */,
965E810A1DD4D5C800D61E4B /* Font.swift in Sources */,
965E810B1DD4D5C800D61E4B /* RobotoFont.swift in Sources */,
......@@ -1002,11 +999,9 @@
965E80E51DD4C53300D61E4B /* PulseAnimation.swift in Sources */,
965E80FE1DD4D59500D61E4B /* ToolbarController.swift in Sources */,
96328B971E05C0BB009A4C90 /* TableView.swift in Sources */,
965E80C81DD4C50600D61E4B /* Animation.swift in Sources */,
965E80F81DD4D59500D61E4B /* ImageCard.swift in Sources */,
96328B991E05C0CE009A4C90 /* TableViewController.swift in Sources */,
965E80F91DD4D59500D61E4B /* PresenterCard.swift in Sources */,
965E80CB1DD4C50600D61E4B /* BasicAnimation.swift in Sources */,
965E80CC1DD4C50600D61E4B /* Bar.swift in Sources */,
965E80CD1DD4C50600D61E4B /* Button.swift in Sources */,
965E80CE1DD4C50600D61E4B /* FABButton.swift in Sources */,
......@@ -1032,6 +1027,7 @@
965E80DB1DD4C50600D61E4B /* InterimSpace.swift in Sources */,
965E80DC1DD4C50600D61E4B /* Depth.swift in Sources */,
965E80DD1DD4C50600D61E4B /* EdgeInsets.swift in Sources */,
96BFC16A1E61DAA10075DE1F /* MotionAnimation.swift in Sources */,
965E80DE1DD4C50600D61E4B /* Gravity.swift in Sources */,
965E80DF1DD4C50600D61E4B /* CornerRadius.swift in Sources */,
965E80FB1DD4D59500D61E4B /* SearchBar.swift in Sources */,
......
/*
* 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(AnimationFillMode)
public enum AnimationFillMode: Int {
case forwards
case backwards
case both
case removed
}
/**
Converts the AnimationFillMode enum value to a corresponding String.
- Parameter mode: An AnimationFillMode enum value.
*/
public func AnimationFillModeToValue(mode: AnimationFillMode) -> String {
switch mode {
case .forwards:
return kCAFillModeForwards
case .backwards:
return kCAFillModeBackwards
case .both:
return kCAFillModeBoth
case .removed:
return kCAFillModeRemoved
}
}
@objc(AnimationTimingFunction)
public enum AnimationTimingFunction: Int {
case `default`
case linear
case easeIn
case easeOut
case easeInEaseOut
}
/**
Converts the AnimationTimingFunction enum value to a corresponding CAMediaTimingFunction.
- Parameter function: An AnimationTimingFunction enum value.
- Returns: A CAMediaTimingFunction.
*/
public func AnimationTimingFunctionToValue(function: AnimationTimingFunction) -> CAMediaTimingFunction {
switch function {
case .default:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
case .linear:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
case .easeIn:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
case .easeOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
case .easeInEaseOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
}
}
public typealias AnimationDelayCancelBlock = (Bool) -> Void
public struct Animation {
/**
Executes a block of code after a time delay.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter execute block: A completion block that is executed once
the animations have completed.
*/
@discardableResult
public static func delay(_ time: TimeInterval, execute block: @escaping () -> Void) -> AnimationDelayCancelBlock? {
func asyncAfter(completion: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time, execute: completion)
}
var cancelable: AnimationDelayCancelBlock?
let delayed: AnimationDelayCancelBlock = {
if !$0 {
DispatchQueue.main.async(execute: block)
}
cancelable = nil
}
cancelable = delayed
asyncAfter {
cancelable?(false)
}
return cancelable;
}
/**
Cancels the delayed AnimationDelayCancelBlock.
- Parameter delayed completion: An AnimationDelayCancelBlock.
*/
public static func cancel(delayed completion: AnimationDelayCancelBlock) {
completion(true)
}
/**
Disables the default animations set on CALayers.
- Parameter animations: A callback that wraps the animations to disable.
*/
public static func disable(animations: (() -> Void)) {
animate(duration: 0, animations: animations)
}
/**
Runs an animation with a specified duration.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter timingFunction: An AnimationTimingFunction value.
- Parameter completion: A completion block that is executed once
the animations have completed.
*/
public static func animate(duration: CFTimeInterval, timingFunction: AnimationTimingFunction = .easeInEaseOut, animations: (() -> Void), completion: (() -> Void)? = nil) {
CATransaction.begin()
CATransaction.setAnimationDuration(duration)
CATransaction.setCompletionBlock(completion)
CATransaction.setAnimationTimingFunction(AnimationTimingFunctionToValue(function: .easeInEaseOut))
animations()
CATransaction.commit()
}
/**
Creates a CAAnimationGroup.
- Parameter animations: An Array of CAAnimation objects.
- Parameter timingFunction: An AnimationTimingFunction value.
- Parameter duration: An animation duration time for the group.
- Returns: A CAAnimationGroup.
*/
public static func animate(group animations: [CAAnimation], timingFunction: AnimationTimingFunction = .easeInEaseOut, duration: CFTimeInterval = 0.5) -> CAAnimationGroup {
let group = CAAnimationGroup()
group.fillMode = AnimationFillModeToValue(mode: .forwards)
group.isRemovedOnCompletion = false
group.animations = animations
group.duration = duration
group.timingFunction = AnimationTimingFunctionToValue(function: timingFunction)
return group
}
/**
Executes an animation block with a given delay and duration.
- Parameter delay time: A CFTimeInterval.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter completion: A completion block that is executed once
the animations have completed.
*/
public static func animate(delay time: CFTimeInterval, duration: CFTimeInterval, animations: @escaping (() -> Void), completion: (() -> Void)? = nil) {
delay(time) {
animate(duration: duration, animations: animations, completion: completion)
}
}
}
/*
* 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
public enum AnimationKeyPath: String {
case backgroundColor
case scale = "transform.scale"
case position
case shadowPath
}
extension CABasicAnimation {
/**
A convenience initializer that takes a given AnimationKeyPath.
- Parameter keyPath: An AnimationKeyPath.
*/
public convenience init(keyPath: AnimationKeyPath) {
self.init(keyPath: keyPath.rawValue)
}
}
extension Animation {
/**
Creates a CABasicAnimation for the backgroundColor key path.
- Parameter color: A UIColor.
- Parameter duration: An animation time duration.
- Returns: A CABasicAnimation.
*/
public static func backgroundColor(color: UIColor, duration: CFTimeInterval? = nil) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: .backgroundColor)
animation.toValue = color.cgColor
animation.fillMode = AnimationFillModeToValue(mode: .forwards)
animation.isRemovedOnCompletion = false
animation.timingFunction = AnimationTimingFunctionToValue(function: .easeInEaseOut)
if let v = duration {
animation.duration = v
}
return animation
}
/**
Creates a CABasicAnimation for the transform.scale key path.
- Parameter by scale: A CGFloat.
- Parameter duration: An animation time duration.
- Returns: A CABasicAnimation.
*/
public static func scale(by scale: CGFloat, duration: CFTimeInterval? = nil) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: .scale)
animation.toValue = scale as NSNumber
animation.fillMode = AnimationFillModeToValue(mode: .forwards)
animation.isRemovedOnCompletion = false
animation.timingFunction = AnimationTimingFunctionToValue(function: .easeInEaseOut)
if let v = duration {
animation.duration = v
}
return animation
}
/**
Creates a CABasicAnimation for the position key path.
- Parameter to point: A CGPoint.
- Parameter duration: An animation time duration.
- Returns: A CABasicAnimation.
*/
public static func position(to point: CGPoint, duration: CFTimeInterval? = nil) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: .position)
animation.toValue = NSValue(cgPoint: point)
animation.fillMode = AnimationFillModeToValue(mode: .forwards)
animation.isRemovedOnCompletion = false
animation.timingFunction = AnimationTimingFunctionToValue(function: .easeInEaseOut)
if let v = duration {
animation.duration = v
}
return animation
}
/**
Creates a CABasicAnimation for the shadowPath key path.
- Parameter to path: A CGPath.
- Parameter duration: An animation time duration.
- Returns: A CABasicAnimation.
*/
public static func shadowPath(to path: CGPath, duration: CFTimeInterval? = nil) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: .shadowPath)
animation.toValue = path
animation.fillMode = AnimationFillModeToValue(mode: .forwards)
animation.isRemovedOnCompletion = false
animation.timingFunction = AnimationTimingFunctionToValue(function: .linear)
if let v = duration {
animation.duration = v
}
return animation
}
}
......@@ -42,6 +42,11 @@ open class Button: UIButton, Pulseable {
/// A Pulse reference.
internal var pulse: Pulse!
/// A reference to the pulse layer.
public var pulseLayer: CALayer? {
return pulse.pulseLayer
}
/// PulseAnimation value.
open var pulseAnimation: PulseAnimation {
get {
......@@ -189,7 +194,7 @@ open class Button: UIButton, Pulseable {
*/
open func pulse(point: CGPoint? = nil) {
pulse.expand(point: point ?? center)
Animation.delay(0.35) { [weak self] in
Motion.delay(0.35) { [weak self] in
self?.pulse.contract()
}
}
......
......@@ -43,6 +43,11 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
/// A Pulse reference.
internal var pulse: Pulse!
/// A reference to the pulse layer.
public var pulseLayer: CALayer? {
return pulse.pulseLayer
}
/// PulseAnimation value.
open var pulseAnimation: PulseAnimation {
get {
......@@ -241,7 +246,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
*/
open func pulse(point: CGPoint? = nil) {
pulse.expand(point: point ?? center)
Animation.delay(0.35) { [weak self] in
Motion.delay(0.35) { [weak self] in
self?.pulse.contract()
}
}
......
......@@ -43,6 +43,11 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
/// A Pulse reference.
internal var pulse: Pulse!
/// A reference to the pulse layer.
public var pulseLayer: CALayer? {
return pulse.pulseLayer
}
/// PulseAnimation value.
open var pulseAnimation: PulseAnimation {
get {
......@@ -199,7 +204,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
*/
open func pulse(point: CGPoint? = nil) {
pulse.expand(point: point ?? center)
Animation.delay(0.35) { [weak self] in
Motion.delay(0.35) { [weak self] in
self?.pulse.contract()
}
}
......
......@@ -248,63 +248,6 @@ extension CALayer {
}
extension CALayer {
/**
A method that accepts CAAnimation objects and executes them on the
view's backing layer.
- Parameter animation: A CAAnimation instance.
*/
open func animate(_ animation: CAAnimation) {
animation.delegate = self
if let a = animation as? CABasicAnimation {
a.fromValue = (presentation() ?? self).value(forKeyPath: a.keyPath!)
}
if let a = animation as? CAPropertyAnimation {
add(a, forKey: a.keyPath!)
} else if let a = animation as? CAAnimationGroup {
add(a, forKey: nil)
} else if let a = animation as? CATransition {
add(a, forKey: kCATransition)
}
}
/**
A delegation method that is executed when the backing layer stops
running an animation.
- Parameter animation: The CAAnimation instance that stopped running.
- Parameter flag: A boolean that indicates if the animation stopped
because it was completed or interrupted. True if completed, false
if interrupted.
*/
open func animationDidStop(_ animation: CAAnimation, finished flag: Bool) {
guard let a = animation as? CAPropertyAnimation else {
if let a = (animation as? CAAnimationGroup)?.animations {
for x in a {
animationDidStop(x, finished: true)
}
}
return
}
guard let b = a as? CABasicAnimation else {
return
}
guard let v = b.toValue else {
return
}
guard let k = b.keyPath else {
return
}
setValue(v, forKeyPath: k)
removeAnimation(forKey: k)
}
}
extension CALayer {
/// Manages the layout for the shape of the view instance.
open func layoutShape() {
guard .none != shapePreset else {
......@@ -337,12 +280,7 @@ extension CALayer {
} else if nil == shadowPath {
shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath
} else {
let a = Animation.shadowPath(to: UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath)
a.fromValue = shadowPath
animate(a)
motion(.shadow(path: UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath))
}
}
}
@available(iOS 10, *)
extension CALayer: CAAnimationDelegate {}
/*
* Copyright (C) 2015 - 2017, 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(MotionAnimationFillMode)
public enum MotionAnimationFillMode: Int {
case forwards
case backwards
case both
case removed
}
/**
Converts the MotionAnimationFillMode enum value to a corresponding String.
- Parameter mode: An MotionAnimationFillMode enum value.
*/
public func MotionAnimationFillModeToValue(mode: MotionAnimationFillMode) -> String {
switch mode {
case .forwards:
return kCAFillModeForwards
case .backwards:
return kCAFillModeBackwards
case .both:
return kCAFillModeBoth
case .removed:
return kCAFillModeRemoved
}
}
@objc(MotionAnimationTimingFunction)
public enum MotionAnimationTimingFunction: Int {
case `default`
case linear
case easeIn
case easeOut
case easeInEaseOut
}
/**
Converts the MotionAnimationTimingFunction enum value to a corresponding CAMediaTimingFunction.
- Parameter function: An MotionAnimationTimingFunction enum value.
- Returns: A CAMediaTimingFunction.
*/
public func MotionAnimationTimingFunctionToValue(timingFunction: MotionAnimationTimingFunction) -> CAMediaTimingFunction {
switch timingFunction {
case .default:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
case .linear:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
case .easeIn:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
case .easeOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
case .easeInEaseOut:
return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
}
}
public typealias MotionDelayCancelBlock = (Bool) -> Void
fileprivate var MotionInstanceKey: UInt8 = 0
fileprivate var MotionInstanceControllerKey: UInt8 = 0
fileprivate struct MotionInstance {
fileprivate var identifier: String
fileprivate var animations: [MotionAnimation]
}
fileprivate struct MotionInstanceController {
fileprivate var isEnabled: Bool
fileprivate weak var delegate: MotionDelegate?
}
extension UIViewController: MotionDelegate, UIViewControllerTransitioningDelegate, UINavigationControllerDelegate, UITabBarControllerDelegate {
/// MotionInstanceController reference.
fileprivate var motionInstanceController: MotionInstanceController {
get {
return AssociatedObject(base: self, key: &MotionInstanceControllerKey) {
return MotionInstanceController(isEnabled: false, delegate: nil)
}
}
set(value) {
AssociateObject(base: self, key: &MotionInstanceControllerKey, value: value)
}
}
/// A boolean that indicates whether motion is enabled.
open var isMotionEnabled: Bool {
get {
return motionInstanceController.isEnabled
}
set(value) {
if value {
modalPresentationStyle = .custom
transitioningDelegate = self
motionDelegate = self
(self as? UINavigationController)?.delegate = self
(self as? UITabBarController)?.delegate = self
}
motionInstanceController.isEnabled = value
}
}
/// A reference to the MotionDelegate.
open weak var motionDelegate: MotionDelegate? {
get {
return motionInstanceController.delegate
}
set(value) {
motionInstanceController.delegate = value
}
}
/**
Determines whether to use a Motion instance for transitions.
- Parameter _ navigationController: A UINavigationController.
- Parameter animationControllerFor operation: A UINavigationControllerOperation.
- Parameter from fromVC: A UIViewController that is being transitioned from.
- Parameter to toVC: A UIViewController that is being transitioned to.
- Returns: An optional UIViewControllerAnimatedTransitioning.
*/
open func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return fromVC.isMotionEnabled ? Motion(isPresenting: operation == .push, isContainer: true) : nil
}
/**
Determines whether to use a Motion instance for transitions.
- Parameter _ tabBarController: A UITabBarController.
- Parameter animationControllerForTransitionFrom fromVC: A UIViewController that is being transitioned from.
- Parameter to toVC: A UIViewController that is being transitioned to.
- Returns: An optional UIViewControllerAnimatedTransitioning.
*/
open func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return fromVC.isMotionEnabled ? Motion(isPresenting: true, isContainer: true) : nil
}
}
extension UIViewController {
/**
Determines whether to use a Motion instance for transitions.
- Parameter forPresented presented: A UIViewController.
- Parameter presenting: A UIViewController.
- Parameter source: A UIViewController.
- Returns: An optional UIViewControllerAnimatedTransitioning.
*/
open func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return isMotionEnabled ? Motion(isPresenting: true, isContainer: false) : nil
}
/**
Determines whether to use a Motion instance for transitions.
- Parameter forDismissed dismissed: A UIViewController.
- Returns: An optional UIViewControllerAnimatedTransitioning.
*/
open func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return isMotionEnabled ? Motion() : nil
}
/**
Determines whether to use a MotionPresentationController for transitions.
- Parameter forPresented presented: A UIViewController.
- Parameter presenting: A UIViewController.
- Parameter source: A UIViewController.
- Returns: An optional UIPresentationController.
*/
open func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return isMotionEnabled ? MotionPresentationController(presentedViewController: presented, presenting: presenting) : nil
}
}
extension UIView {
/// MotionInstance reference.
fileprivate var motionInstance: MotionInstance {
get {
return AssociatedObject(base: self, key: &MotionInstanceKey) {
return MotionInstance(identifier: "", animations: [])
}
}
set(value) {
AssociateObject(base: self, key: &MotionInstanceKey, value: value)
}
}
/// An identifier value used to connect views across UIViewControllers.
open var motionIdentifier: String {
get {
return motionInstance.identifier
}
set(value) {
motionInstance.identifier = value
}
}
/// The animations to run while in transition.
open var motionAnimations: [MotionAnimation] {
get {
return motionInstance.animations
}
set(value) {
motionInstance.animations = value
}
}
}
extension UIView {
/**
Snapshots the view instance for animations during transitions.
- Parameter afterUpdates: A boolean indicating whether to snapshot the view
after a render update, or as is.
- Parameter shouldHide: A boolean indicating whether the view should be hidden
after the snapshot is taken.
- Returns: A UIView instance that is a snapshot of the given UIView.
*/
open func transitionSnapshot(afterUpdates: Bool, shouldHide: Bool = true) -> UIView {
isHidden = false
// Material specific.
(self as? Pulseable)?.pulseLayer?.isHidden = true
let oldCornerRadius = layer.cornerRadius
layer.cornerRadius = 0
var oldBackgroundColor: UIColor?
if shouldHide {
oldBackgroundColor = backgroundColor
backgroundColor = .clear
}
let oldTransform = motionTransform
motionTransform = CATransform3DIdentity
let v = snapshotView(afterScreenUpdates: afterUpdates)!
layer.cornerRadius = oldCornerRadius
if shouldHide {
backgroundColor = oldBackgroundColor
}
motionTransform = oldTransform
let contentView = v.subviews.first!
contentView.layer.cornerRadius = layer.cornerRadius
contentView.layer.masksToBounds = true
v.motionIdentifier = motionIdentifier
v.layer.position = motionPosition
v.bounds = bounds
v.layer.cornerRadius = layer.cornerRadius
v.layer.zPosition = layer.zPosition
v.layer.opacity = layer.opacity
v.isOpaque = isOpaque
v.layer.anchorPoint = layer.anchorPoint
v.layer.masksToBounds = layer.masksToBounds
v.layer.borderColor = layer.borderColor
v.layer.borderWidth = layer.borderWidth
v.layer.shadowRadius = layer.shadowRadius
v.layer.shadowOpacity = layer.shadowOpacity
v.layer.shadowColor = layer.shadowColor
v.layer.shadowOffset = layer.shadowOffset
v.contentMode = contentMode
v.motionTransform = motionTransform
v.backgroundColor = backgroundColor
// Material specific.
(self as? Pulseable)?.pulseLayer?.isHidden = false
isHidden = shouldHide
return v
}
}
open class MotionPresentationController: UIPresentationController {
open override func presentationTransitionWillBegin() {
guard nil != containerView else {
return
}
presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (context) in
print("Animating")
})
print("presentationTransitionWillBegin")
}
open override func presentationTransitionDidEnd(_ completed: Bool) {
print("presentationTransitionDidEnd")
}
open override func dismissalTransitionWillBegin() {
guard nil != containerView else {
return
}
presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (context) in
print("Animating")
})
print("dismissalTransitionWillBegin")
}
open override func dismissalTransitionDidEnd(_ completed: Bool) {
print("dismissalTransitionDidEnd")
}
open override var frameOfPresentedViewInContainerView: CGRect {
return containerView?.bounds ?? .zero
}
}
@objc(MotionDelegate)
public protocol MotionDelegate {
@objc
optional func motion(motion: Motion, willTransition fromView: UIView, toView: UIView)
@objc
optional func motion(motion: Motion, didTransition fromView: UIView, toView: UIView)
@objc
optional func motionDelayTransitionByTimeInterval(motion: Motion) -> TimeInterval
}
open class Motion: NSObject {
/// A boolean indicating whether Motion is presenting a view controller.
open fileprivate(set) var isPresenting: Bool
/// A boolean indicating whether the view controller is a container.
open fileprivate(set) var isContainer: Bool
/**
An Array of UIView pairs with common motionIdentifiers in
the from and to view controllers.
*/
open fileprivate(set) var transitionPairs = [(UIView, UIView)]()
/// A reference to the transition snapshot.
open var transitionSnapshot: UIView!
/// A reference to the transition background view.
open let transitionBackgroundView = UIView()
/// A reference to the view controller that is being transitioned to.
open var toViewController: UIViewController {
return transitionContext.viewController(forKey: .to)!
}
/// A reference to the view controller that is being transitioned from.
open var fromViewController: UIViewController {
return transitionContext.viewController(forKey: .from)!
}
/// The transition context for the current transition.
open var transitionContext: UIViewControllerContextTransitioning!
/// The transition delay time.
open var delay: TimeInterval = 0
/// The transition duration time.
open var duration: TimeInterval = 0.35
/// The transition container view.
open var containerView: UIView!
/// The view that is used to animate the transitions between view controllers.
open var transitionView = UIView()
/// The view that is being transitioned to.
open var toView: UIView {
return transitionContext.view(forKey: .to)!
}
/// The subviews of the view being transitioned to.
open var toSubviews: [UIView] {
return Motion.subviews(of: toView)
}
/// The view that is being transitioned from.
open var fromView: UIView {
return transitionContext.view(forKey: .from)!
}
/// The subviews of the view being transitioned from.
open var fromSubviews: [UIView] {
return Motion.subviews(of: fromView)
}
/// A time value to delay the transition animation by.
fileprivate var delayTransitionByTimeInterval: TimeInterval {
return fromViewController.motionDelegate?.motionDelayTransitionByTimeInterval?(motion: self) ?? 0
}
/// The default initializer.
public override init() {
isPresenting = false
isContainer = false
super.init()
}
/**
An initializer to modify the presenting and container state.
- Parameter isPresenting: A boolean value indicating if the
Motion instance is presenting the view controller.
- Parameter isContainer: A boolean value indicating if the
Motion instance is a container view controller.
*/
public init(isPresenting: Bool, isContainer: Bool) {
self.isPresenting = isPresenting
self.isContainer = isContainer
super.init()
}
/// Returns an Array of subviews for a given subview.
fileprivate class func subviews(of view: UIView) -> [UIView] {
var views: [UIView] = []
Motion.subviews(of: view, views: &views)
return views
}
/// Populates an Array of views that are subviews of a given view.
fileprivate class func subviews(of view: UIView, views: inout [UIView]) {
for v in view.subviews {
if 0 < v.motionIdentifier.utf16.count {
views.append(v)
}
subviews(of: v, views: &views)
}
}
/**
Executes a block of code after a time delay.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter execute block: A completion block that is executed once
the animations have completed.
*/
@discardableResult
open class func delay(_ time: TimeInterval, execute block: @escaping () -> Void) -> MotionDelayCancelBlock? {
func asyncAfter(completion: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + time, execute: completion)
}
var cancelable: MotionDelayCancelBlock?
let delayed: MotionDelayCancelBlock = {
if !$0 {
DispatchQueue.main.async(execute: block)
}
cancelable = nil
}
cancelable = delayed
asyncAfter {
cancelable?(false)
}
return cancelable
}
/**
Cancels the delayed MotionDelayCancelBlock.
- Parameter delayed completion: An MotionDelayCancelBlock.
*/
open class func cancel(delayed completion: MotionDelayCancelBlock) {
completion(true)
}
/**
Disables the default animations set on CALayers.
- Parameter animations: A callback that wraps the animations to disable.
*/
open class func disable(_ animations: (() -> Void)) {
animate(duration: 0, animations: animations)
}
/**
Runs an animation with a specified duration.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter timingFunction: An MotionAnimationTimingFunction value.
- Parameter completion: A completion block that is executed once
the animations have completed.
*/
open class func animate(duration: CFTimeInterval, timingFunction: MotionAnimationTimingFunction = .easeInEaseOut, animations: (() -> Void), completion: (() -> Void)? = nil) {
CATransaction.begin()
CATransaction.setAnimationDuration(duration)
CATransaction.setCompletionBlock(completion)
CATransaction.setAnimationTimingFunction(MotionAnimationTimingFunctionToValue(timingFunction: timingFunction))
animations()
CATransaction.commit()
}
}
extension Motion: UIViewControllerAnimatedTransitioning {
/**
The animation method that is used to coordinate the transition.
- Parameter using transitionContext: A UIViewControllerContextTransitioning.
*/
@objc(animateTransition:)
open func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext
fromViewController.motionDelegate?.motion?(motion: self, willTransition: fromView, toView: toView)
Motion.delay(delayTransitionByTimeInterval) { [weak self] in
guard let s = self else {
return
}
s.prepareContainerView()
s.prepareTransitionSnapshot()
s.prepareTransitionPairs()
s.prepareTransitionView()
s.prepareTransitionBackgroundView()
s.prepareToView()
s.prepareTransitionAnimation()
}
}
/**
Returns the transition duration time interval.
- Parameter using transitionContext: An optional UIViewControllerContextTransitioning.
- Returns: A TimeInterval that is the total animation time including delays.
*/
@objc(transitionDuration:)
open func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return delay + duration
}
}
extension Motion {
/// Prepares the containerView.
fileprivate func prepareContainerView() {
containerView = transitionContext.containerView
}
/// Prepares the transitionSnapshot.
fileprivate func prepareTransitionSnapshot() {
transitionSnapshot = fromView.transitionSnapshot(afterUpdates: true, shouldHide: false)
transitionSnapshot.frame = fromView.bounds
containerView.insertSubview(transitionSnapshot, aboveSubview: fromView)
}
/// Prepares the transitionPairs.
fileprivate func prepareTransitionPairs() {
for from in fromSubviews {
for to in toSubviews {
guard to.motionIdentifier == from.motionIdentifier else {
continue
}
transitionPairs.append((from, to))
}
}
}
/// Prepares the transitionView.
fileprivate func prepareTransitionView() {
transitionView.frame = toView.bounds
transitionView.isUserInteractionEnabled = false
containerView.insertSubview(transitionView, belowSubview: transitionSnapshot)
}
/// Prepares the transitionBackgroundView.
fileprivate func prepareTransitionBackgroundView() {
transitionBackgroundView.backgroundColor = isPresenting ? .clear : fromView.backgroundColor ?? .clear
transitionBackgroundView.frame = transitionView.bounds
transitionView.addSubview(transitionBackgroundView)
}
/// Prepares the toView.
fileprivate func prepareToView() {
toView.isHidden = isPresenting
containerView.insertSubview(toView, belowSubview: transitionView)
toView.updateConstraints()
toView.setNeedsLayout()
toView.layoutIfNeeded()
}
/// Prepares the transition animation.
fileprivate func prepareTransitionAnimation() {
addTransitionAnimations()
addBackgroundAnimation()
cleanUpAnimation()
removeTransitionSnapshot()
}
}
extension Motion {
/// Adds the available transition animations.
fileprivate func addTransitionAnimations() {
for (from, to) in transitionPairs {
var snapshotAnimations = [CABasicAnimation]()
var snapshotChildAnimations = [CABasicAnimation]()
let sizeAnimation = Motion.size(to.bounds.size)
let cornerRadiusAnimation = Motion.corner(radius: to.layer.cornerRadius)
snapshotAnimations.append(sizeAnimation)
snapshotAnimations.append(cornerRadiusAnimation)
snapshotAnimations.append(Motion.position(to: to.motionPosition))
snapshotAnimations.append(Motion.transform(transform: to.motionTransform))
snapshotAnimations.append(Motion.background(color: to.backgroundColor ?? .clear))
snapshotChildAnimations.append(cornerRadiusAnimation)
snapshotChildAnimations.append(sizeAnimation)
snapshotChildAnimations.append(Motion.position(x: to.bounds.width / 2, y: to.bounds.height / 2))
let d = calculateAnimationTransitionDuration(animations: to.motionAnimations)
let snapshot = from.transitionSnapshot(afterUpdates: true)
transitionView.addSubview(snapshot)
Motion.delay(calculateAnimationDelayTimeInterval(animations: to.motionAnimations)) { [weak self, weak to] in
guard let s = self else {
return
}
guard let v = to else {
return
}
let tf = s.calculateAnimationTimingFunction(animations: v.motionAnimations)
let snapshotGroup = Motion.animate(group: snapshotAnimations, duration: d)
snapshotGroup.fillMode = MotionAnimationFillModeToValue(mode: .forwards)
snapshotGroup.isRemovedOnCompletion = false
snapshotGroup.timingFunction = MotionAnimationTimingFunctionToValue(timingFunction: tf)
let snapshotChildGroup = Motion.animate(group: snapshotChildAnimations, duration: d)
snapshotChildGroup.fillMode = MotionAnimationFillModeToValue(mode: .forwards)
snapshotChildGroup.isRemovedOnCompletion = false
snapshotChildGroup.timingFunction = MotionAnimationTimingFunctionToValue(timingFunction: tf)
snapshot.animate(snapshotGroup)
snapshot.subviews.first?.animate(snapshotChildGroup)
}
}
}
/// Adds the background animation.
fileprivate func addBackgroundAnimation() {
transitionBackgroundView.motion(.backgroundColor(isPresenting ? toView.backgroundColor ?? .clear : .clear), .duration(transitionDuration(using: transitionContext)))
}
}
extension Motion {
/**
Creates a CAAnimationGroup.
- Parameter animations: An Array of CAAnimation objects.
- Parameter timingFunction: An MotionAnimationTimingFunction value.
- Parameter duration: An animation duration time for the group.
- Returns: A CAAnimationGroup.
*/
open class func animate(group animations: [CAAnimation], timingFunction: MotionAnimationTimingFunction = .easeInEaseOut, duration: CFTimeInterval = 0.5) -> CAAnimationGroup {
let group = CAAnimationGroup()
group.fillMode = MotionAnimationFillModeToValue(mode: .forwards)
group.isRemovedOnCompletion = false
group.animations = animations
group.duration = duration
group.timingFunction = MotionAnimationTimingFunctionToValue(timingFunction: timingFunction)
return group
}
}
extension Motion {
/**
Calculates the animation delay time based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A TimeInterval.
*/
fileprivate func calculateAnimationDelayTimeInterval(animations: [MotionAnimation]) -> TimeInterval {
var t: TimeInterval = 0
for a in animations {
switch a {
case let .delay(time):
if time > delay {
delay = time
}
t = time
default:break
}
}
return t
}
/**
Calculates the animation transition duration based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A TimeInterval.
*/
fileprivate func calculateAnimationTransitionDuration(animations: [MotionAnimation]) -> TimeInterval {
var t: TimeInterval = 0.35
for a in animations {
switch a {
case let .duration(time):
if time > duration {
duration = time
}
t = time
default:break
}
}
return t
}
/**
Calculates the animation timing function based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A MotionAnimationTimingFunction.
*/
fileprivate func calculateAnimationTimingFunction(animations: [MotionAnimation]) -> MotionAnimationTimingFunction {
var t = MotionAnimationTimingFunction.easeInEaseOut
for a in animations {
switch a {
case let .timingFunction(timingFunction):
t = timingFunction
default:break
}
}
return t
}
}
extension Motion {
/// Cleans up the animation transition.
fileprivate func cleanUpAnimation() {
Motion.delay(transitionDuration(using: transitionContext) + delayTransitionByTimeInterval) { [weak self] in
guard let s = self else {
return
}
s.showToSubviews()
s.removeTransitionView()
s.clearTransitionPairs()
s.completeTransition()
}
}
/// Removes the transitionSnapshot from its superview.
fileprivate func removeTransitionSnapshot() {
Motion.delay(delay) { [weak self] in
self?.transitionSnapshot.removeFromSuperview()
}
}
/// Shows the toView and its subviews.
fileprivate func showToSubviews() {
toSubviews.forEach {
$0.isHidden = false
}
toView.isHidden = false
}
/// Clears the transitionPairs Array.
fileprivate func clearTransitionPairs() {
transitionPairs.removeAll()
}
/// Removes the transitionView.
fileprivate func removeTransitionView() {
transitionView.removeFromSuperview()
}
/// Calls the completionTransition method.
fileprivate func completeTransition() {
toViewController.motionDelegate?.motion?(motion: self, didTransition: fromView, toView: toView)
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
......@@ -93,6 +93,9 @@ public enum MotionAnimation {
case size(width: CGFloat, height: CGFloat)
}
@available(iOS 10, *)
extension CALayer: CAAnimationDelegate {}
extension CALayer {
/**
......@@ -111,7 +114,10 @@ extension CALayer {
*/
open func animate(_ animations: [CAAnimation]) {
for animation in animations {
if nil == animation.delegate {
animation.delegate = self
}
if let a = animation as? CABasicAnimation {
a.fromValue = (presentation() ?? self).value(forKeyPath: a.keyPath!)
}
......@@ -126,6 +132,8 @@ extension CALayer {
}
}
open func animationDidStart(_ anim: CAAnimation) {}
/**
A delegation function that is executed when the backing layer stops
running an animation.
......@@ -134,9 +142,9 @@ extension CALayer {
because it was completed or interrupted. True if completed, false
if interrupted.
*/
open func animationDidStop(_ animation: CAAnimation, finished flag: Bool) {
guard let a = animation as? CAPropertyAnimation else {
if let a = (animation as? CAAnimationGroup)?.animations {
open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
guard let a = anim as? CAPropertyAnimation else {
if let a = (anim as? CAAnimationGroup)?.animations {
for x in a {
animationDidStop(x, finished: true)
}
......@@ -173,7 +181,7 @@ extension CALayer {
- Parameter animations: An Array of MotionAnimation values.
*/
open func motion(_ animations: [MotionAnimation]) {
motion(delay: 0, duration: 0.25, timingFunction: .easeInEaseOut, animations: animations)
motion(delay: 0, duration: 0.35, timingFunction: .easeInEaseOut, animations: animations)
}
/**
......@@ -315,9 +323,6 @@ extension CALayer {
}
}
@available(iOS 10, *)
extension CALayer: CAAnimationDelegate {}
extension UIView {
/// Computes the rotation of the view.
open var motionRotationAngle: CGFloat {
......@@ -331,7 +336,7 @@ extension UIView {
/// The global position of a view.
open var motionPosition: CGPoint {
return superview?.convert(position, to: nil) ?? position
return superview?.convert(layer.position, to: nil) ?? layer.position
}
/// The layer.transform of a view.
......
......@@ -51,6 +51,9 @@ public protocol Pulseable {
/// The opcaity value for the pulse animation.
var pulseOpacity: CGFloat { get set }
/// A reference to the pulse layer.
var pulseLayer: CALayer? { get }
}
public struct Pulse {
......@@ -58,7 +61,7 @@ public struct Pulse {
fileprivate weak var pulseView: UIView?
/// The layer the pulse layers are added to.
fileprivate weak var pulseLayer: CALayer?
internal weak var pulseLayer: CALayer?
/// Pulse layers.
fileprivate var layers = [CAShapeLayer]()
......@@ -114,7 +117,7 @@ public struct Pulse {
let w = view.bounds.width
let h = view.bounds.height
Animation.disable(animations: { [
Motion.disable({ [
n = .center == animation ? w < h ? w : h : w < h ? h : w,
bounds = layer.bounds,
animation = animation,
......@@ -143,17 +146,17 @@ public struct Pulse {
switch animation {
case .centerWithBacking, .backing, .pointWithBacking:
bLayer.add(Animation.backgroundColor(color: color.withAlphaComponent(opacity / 2), duration: duration), forKey: nil)
bLayer.motion(.backgroundColor(color.withAlphaComponent(opacity / 2)), .duration(duration))
default:break
}
switch animation {
case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking:
pLayer.add(Animation.scale(by: 1, duration: duration), forKey: nil)
pLayer.motion(.scale(1), .duration(duration))
default:break
}
Animation.delay(duration) {
Motion.delay(duration) {
bLayer.setValue(true, forKey: "animated")
}
}
......@@ -168,7 +171,7 @@ public struct Pulse {
return
}
Animation.delay(animated ? 0 : 0.15) { [animation = animation, color = color] in
Motion.delay(animated ? 0 : 0.15) { [animation = animation, color = color] in
guard let pLayer = bLayer.sublayers?.first as? CAShapeLayer else {
return
}
......@@ -177,20 +180,17 @@ public struct Pulse {
switch animation {
case .centerWithBacking, .backing, .pointWithBacking:
bLayer.add(Animation.backgroundColor(color: color.withAlphaComponent(0), duration: duration), forKey: nil)
bLayer.motion(.backgroundColor(color.withAlphaComponent(0)), .duration(duration))
default:break
}
switch animation {
case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking:
pLayer.add(Animation.animate(group: [
Animation.scale(by: .center == animation ? 1 : 1.325),
Animation.backgroundColor(color: color.withAlphaComponent(0))
], duration: duration), forKey: nil)
pLayer.motion(.scale(.center == animation ? 1 : 1.325), .backgroundColor(color.withAlphaComponent(0)))
default:break
}
Animation.delay(duration) {
Motion.delay(duration) {
pLayer.removeFromSuperlayer()
bLayer.removeFromSuperlayer()
}
......
......@@ -34,6 +34,11 @@ open class PulseView: View, Pulseable {
/// A Pulse reference.
internal var pulse: Pulse!
/// A reference to the pulse layer.
public var pulseLayer: CALayer? {
return pulse.pulseLayer
}
/// PulseAnimation value.
open var pulseAnimation: PulseAnimation {
get {
......@@ -73,7 +78,7 @@ open class PulseView: View, Pulseable {
*/
open func pulse(point: CGPoint? = nil) {
pulse.expand(point: point ?? center)
Animation.delay(0.35) { [weak self] in
Motion.delay(0.35) { [weak self] in
self?.pulse.contract()
}
}
......
......@@ -122,8 +122,8 @@ open class SnackbarController: RootController {
- Parameter status: A SnackbarStatus enum value.
*/
@discardableResult
open func animate(snackbar status: SnackbarStatus, delay: TimeInterval = 0, animations: ((Snackbar) -> Void)? = nil, completion: ((Snackbar) -> Void)? = nil) -> AnimationDelayCancelBlock? {
return Animation.delay(delay) { [weak self, status = status, animations = animations, completion = completion] in
open func animate(snackbar status: SnackbarStatus, delay: TimeInterval = 0, animations: ((Snackbar) -> Void)? = nil, completion: ((Snackbar) -> Void)? = nil) -> MotionDelayCancelBlock? {
return Motion.delay(delay) { [weak self, status = status, animations = animations, completion = completion] in
guard let s = self else {
return
}
......
......@@ -42,6 +42,11 @@ open class TableViewCell: UITableViewCell, Pulseable {
/// A Pulse reference.
internal var pulse: Pulse!
/// A reference to the pulse layer.
public var pulseLayer: CALayer? {
return pulse.pulseLayer
}
/// PulseAnimation value.
open var pulseAnimation: PulseAnimation {
get {
......@@ -115,7 +120,7 @@ open class TableViewCell: UITableViewCell, Pulseable {
*/
open func pulse(point: CGPoint? = nil) {
pulse.expand(point: point ?? center)
Animation.delay(0.35) { [weak self] in
Motion.delay(0.35) { [weak self] in
self?.pulse.contract()
}
}
......
/*
* Copyright (C) 2015 - 2017, 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 AppKit
@objc(ColorPalette)
public protocol ColorPalette {
static var lighten5: NSColor { get }
static var lighten4: NSColor { get }
static var lighten3: NSColor { get }
static var lighten2: NSColor { get }
static var lighten1: NSColor { get }
static var base: NSColor { get }
static var darken1: NSColor { get }
static var darken2: NSColor { get }
static var darken3: NSColor { get }
static var darken4: NSColor { get }
@objc
optional static var accent1: NSColor { get }
@objc
optional static var accent2: NSColor { get }
@objc
optional static var accent3: NSColor { get }
@objc
optional static var accent4: NSColor { get }
}
open class Color: NSColor {
// dark text
open class darkText {
open static let primary = Color.black.withAlphaComponent(0.87)
open static let secondary = Color.black.withAlphaComponent(0.54)
open static let others = Color.black.withAlphaComponent(0.38)
open static let dividers = Color.black.withAlphaComponent(0.12)
}
// light text
open class lightText {
open static let primary = Color.white
open static let secondary = Color.white.withAlphaComponent(0.7)
open static let others = Color.white.withAlphaComponent(0.5)
open static let dividers = Color.white.withAlphaComponent(0.12)
}
// red
open class red: ColorPalette {
open static let lighten5 = NSColor(red: 255/255, green: 235/255, blue: 238/255, alpha: 1)
open static let lighten4 = NSColor(red: 255/255, green: 205/255, blue: 210/255, alpha: 1)
open static let lighten3 = NSColor(red: 239/255, green: 154/255, blue: 154/255, alpha: 1)
open static let lighten2 = NSColor(red: 229/255, green: 115/255, blue: 115/255, alpha: 1)
open static let lighten1 = NSColor(red: 229/255, green: 83/255, blue: 80/255, alpha: 1)
open static let base = NSColor(red: 244/255, green: 67/255, blue: 54/255, alpha: 1)
open static let darken1 = NSColor(red: 229/255, green: 57/255, blue: 53/255, alpha: 1)
open static let darken2 = NSColor(red: 211/255, green: 47/255, blue: 47/255, alpha: 1)
open static let darken3 = NSColor(red: 198/255, green: 40/255, blue: 40/255, alpha: 1)
open static let darken4 = NSColor(red: 183/255, green: 28/255, blue: 28/255, alpha: 1)
open static let accent1 = NSColor(red: 255/255, green: 138/255, blue: 128/255, alpha: 1)
open static let accent2 = NSColor(red: 255/255, green: 82/255, blue: 82/255, alpha: 1)
open static let accent3 = NSColor(red: 255/255, green: 23/255, blue: 68/255, alpha: 1)
open static let accent4 = NSColor(red: 213/255, green: 0/255, blue: 0/255, alpha: 1)
}
// pink
open class pink: ColorPalette {
open static let lighten5 = NSColor(red: 252/255, green: 228/255, blue: 236/255, alpha: 1)
open static let lighten4 = NSColor(red: 248/255, green: 187/255, blue: 208/255, alpha: 1)
open static let lighten3 = NSColor(red: 244/255, green: 143/255, blue: 177/255, alpha: 1)
open static let lighten2 = NSColor(red: 240/255, green: 98/255, blue: 146/255, alpha: 1)
open static let lighten1 = NSColor(red: 236/255, green: 64/255, blue: 122/255, alpha: 1)
open static let base = NSColor(red: 233/255, green: 30/255, blue: 99/255, alpha: 1)
open static let darken1 = NSColor(red: 216/255, green: 27/255, blue: 96/255, alpha: 1)
open static let darken2 = NSColor(red: 194/255, green: 24/255, blue: 91/255, alpha: 1)
open static let darken3 = NSColor(red: 173/255, green: 20/255, blue: 87/255, alpha: 1)
open static let darken4 = NSColor(red: 136/255, green: 14/255, blue: 79/255, alpha: 1)
open static let accent1 = NSColor(red: 255/255, green: 128/255, blue: 171/255, alpha: 1)
open static let accent2 = NSColor(red: 255/255, green: 64/255, blue: 129/255, alpha: 1)
open static let accent3 = NSColor(red: 245/255, green: 0/255, blue: 87/255, alpha: 1)
open static let accent4 = NSColor(red: 197/255, green: 17/255, blue: 98/255, alpha: 1)
}
// purple
open class purple: ColorPalette {
open static let lighten5 = NSColor(red: 243/255, green: 229/255, blue: 245/255, alpha: 1)
open static let lighten4 = NSColor(red: 225/255, green: 190/255, blue: 231/255, alpha: 1)
open static let lighten3 = NSColor(red: 206/255, green: 147/255, blue: 216/255, alpha: 1)
open static let lighten2 = NSColor(red: 186/255, green: 104/255, blue: 200/255, alpha: 1)
open static let lighten1 = NSColor(red: 171/255, green: 71/255, blue: 188/255, alpha: 1)
open static let base = NSColor(red: 156/255, green: 39/255, blue: 176/255, alpha: 1)
open static let darken1 = NSColor(red: 142/255, green: 36/255, blue: 170/255, alpha: 1)
open static let darken2 = NSColor(red: 123/255, green: 31/255, blue: 162/255, alpha: 1)
open static let darken3 = NSColor(red: 106/255, green: 27/255, blue: 154/255, alpha: 1)
open static let darken4 = NSColor(red: 74/255, green: 20/255, blue: 140/255, alpha: 1)
open static let accent1 = NSColor(red: 234/255, green: 128/255, blue: 252/255, alpha: 1)
open static let accent2 = NSColor(red: 224/255, green: 64/255, blue: 251/255, alpha: 1)
open static let accent3 = NSColor(red: 213/255, green: 0/255, blue: 249/255, alpha: 1)
open static let accent4 = NSColor(red: 170/255, green: 0/255, blue: 255/255, alpha: 1)
}
// deepPurple
open class deepPurple: ColorPalette {
open static let lighten5 = NSColor(red: 237/255, green: 231/255, blue: 246/255, alpha: 1)
open static let lighten4 = NSColor(red: 209/255, green: 196/255, blue: 233/255, alpha: 1)
open static let lighten3 = NSColor(red: 179/255, green: 157/255, blue: 219/255, alpha: 1)
open static let lighten2 = NSColor(red: 149/255, green: 117/255, blue: 205/255, alpha: 1)
open static let lighten1 = NSColor(red: 126/255, green: 87/255, blue: 194/255, alpha: 1)
open static let base = NSColor(red: 103/255, green: 58/255, blue: 183/255, alpha: 1)
open static let darken1 = NSColor(red: 94/255, green: 53/255, blue: 177/255, alpha: 1)
open static let darken2 = NSColor(red: 81/255, green: 45/255, blue: 168/255, alpha: 1)
open static let darken3 = NSColor(red: 69/255, green: 39/255, blue: 160/255, alpha: 1)
open static let darken4 = NSColor(red: 49/255, green: 27/255, blue: 146/255, alpha: 1)
open static let accent1 = NSColor(red: 179/255, green: 136/255, blue: 255/255, alpha: 1)
open static let accent2 = NSColor(red: 124/255, green: 77/255, blue: 255/255, alpha: 1)
open static let accent3 = NSColor(red: 101/255, green: 31/255, blue: 255/255, alpha: 1)
open static let accent4 = NSColor(red: 98/255, green: 0/255, blue: 234/255, alpha: 1)
}
// indigo
open class indigo: ColorPalette {
open static let lighten5 = NSColor(red: 232/255, green: 234/255, blue: 246/255, alpha: 1)
open static let lighten4 = NSColor(red: 197/255, green: 202/255, blue: 233/255, alpha: 1)
open static let lighten3 = NSColor(red: 159/255, green: 168/255, blue: 218/255, alpha: 1)
open static let lighten2 = NSColor(red: 121/255, green: 134/255, blue: 203/255, alpha: 1)
open static let lighten1 = NSColor(red: 92/255, green: 107/255, blue: 192/255, alpha: 1)
open static let base = NSColor(red: 63/255, green: 81/255, blue: 181/255, alpha: 1)
open static let darken1 = NSColor(red: 57/255, green: 73/255, blue: 171/255, alpha: 1)
open static let darken2 = NSColor(red: 48/255, green: 63/255, blue: 159/255, alpha: 1)
open static let darken3 = NSColor(red: 40/255, green: 53/255, blue: 147/255, alpha: 1)
open static let darken4 = NSColor(red: 26/255, green: 35/255, blue: 126/255, alpha: 1)
open static let accent1 = NSColor(red: 140/255, green: 158/255, blue: 255/255, alpha: 1)
open static let accent2 = NSColor(red: 83/255, green: 109/255, blue: 254/255, alpha: 1)
open static let accent3 = NSColor(red: 61/255, green: 90/255, blue: 254/255, alpha: 1)
open static let accent4 = NSColor(red: 48/255, green: 79/255, blue: 254/255, alpha: 1)
}
// blue
open class blue: ColorPalette {
open static let lighten5 = NSColor(red: 227/255, green: 242/255, blue: 253/255, alpha: 1)
open static let lighten4 = NSColor(red: 187/255, green: 222/255, blue: 251/255, alpha: 1)
open static let lighten3 = NSColor(red: 144/255, green: 202/255, blue: 249/255, alpha: 1)
open static let lighten2 = NSColor(red: 100/255, green: 181/255, blue: 246/255, alpha: 1)
open static let lighten1 = NSColor(red: 66/255, green: 165/255, blue: 245/255, alpha: 1)
open static let base = NSColor(red: 33/255, green: 150/255, blue: 243/255, alpha: 1)
open static let darken1 = NSColor(red: 30/255, green: 136/255, blue: 229/255, alpha: 1)
open static let darken2 = NSColor(red: 25/255, green: 118/255, blue: 210/255, alpha: 1)
open static let darken3 = NSColor(red: 21/255, green: 101/255, blue: 192/255, alpha: 1)
open static let darken4 = NSColor(red: 13/255, green: 71/255, blue: 161/255, alpha: 1)
open static let accent1 = NSColor(red: 130/255, green: 177/255, blue: 255/255, alpha: 1)
open static let accent2 = NSColor(red: 68/255, green: 138/255, blue: 255/255, alpha: 1)
open static let accent3 = NSColor(red: 41/255, green: 121/255, blue: 255/255, alpha: 1)
open static let accent4 = NSColor(red: 41/255, green: 98/255, blue: 255/255, alpha: 1)
}
// light blue
open class lightBlue: ColorPalette {
open static let lighten5 = NSColor(red: 225/255, green: 245/255, blue: 254/255, alpha: 1)
open static let lighten4 = NSColor(red: 179/255, green: 229/255, blue: 252/255, alpha: 1)
open static let lighten3 = NSColor(red: 129/255, green: 212/255, blue: 250/255, alpha: 1)
open static let lighten2 = NSColor(red: 79/255, green: 195/255, blue: 247/255, alpha: 1)
open static let lighten1 = NSColor(red: 41/255, green: 182/255, blue: 246/255, alpha: 1)
open static let base = NSColor(red: 3/255, green: 169/255, blue: 244/255, alpha: 1)
open static let darken1 = NSColor(red: 3/255, green: 155/255, blue: 229/255, alpha: 1)
open static let darken2 = NSColor(red: 2/255, green: 136/255, blue: 209/255, alpha: 1)
open static let darken3 = NSColor(red: 2/255, green: 119/255, blue: 189/255, alpha: 1)
open static let darken4 = NSColor(red: 1/255, green: 87/255, blue: 155/255, alpha: 1)
open static let accent1 = NSColor(red: 128/255, green: 216/255, blue: 255/255, alpha: 1)
open static let accent2 = NSColor(red: 64/255, green: 196/255, blue: 255/255, alpha: 1)
open static let accent3 = NSColor(red: 0/255, green: 176/255, blue: 255/255, alpha: 1)
open static let accent4 = NSColor(red: 0/255, green: 145/255, blue: 234/255, alpha: 1)
}
// cyan
open class cyan: ColorPalette {
open static let lighten5 = NSColor(red: 224/255, green: 247/255, blue: 250/255, alpha: 1)
open static let lighten4 = NSColor(red: 178/255, green: 235/255, blue: 242/255, alpha: 1)
open static let lighten3 = NSColor(red: 128/255, green: 222/255, blue: 234/255, alpha: 1)
open static let lighten2 = NSColor(red: 77/255, green: 208/255, blue: 225/255, alpha: 1)
open static let lighten1 = NSColor(red: 38/255, green: 198/255, blue: 218/255, alpha: 1)
open static let base = NSColor(red: 0/255, green: 188/255, blue: 212/255, alpha: 1)
open static let darken1 = NSColor(red: 0/255, green: 172/255, blue: 193/255, alpha: 1)
open static let darken2 = NSColor(red: 0/255, green: 151/255, blue: 167/255, alpha: 1)
open static let darken3 = NSColor(red: 0/255, green: 131/255, blue: 143/255, alpha: 1)
open static let darken4 = NSColor(red: 0/255, green: 96/255, blue: 100/255, alpha: 1)
open static let accent1 = NSColor(red: 132/255, green: 255/255, blue: 255/255, alpha: 1)
open static let accent2 = NSColor(red: 24/255, green: 255/255, blue: 255/255, alpha: 1)
open static let accent3 = NSColor(red: 0/255, green: 229/255, blue: 255/255, alpha: 1)
open static let accent4 = NSColor(red: 0/255, green: 184/255, blue: 212/255, alpha: 1)
}
// teal
open class teal: ColorPalette {
open static let lighten5 = NSColor(red: 224/255, green: 242/255, blue: 241/255, alpha: 1)
open static let lighten4 = NSColor(red: 178/255, green: 223/255, blue: 219/255, alpha: 1)
open static let lighten3 = NSColor(red: 128/255, green: 203/255, blue: 196/255, alpha: 1)
open static let lighten2 = NSColor(red: 77/255, green: 182/255, blue: 172/255, alpha: 1)
open static let lighten1 = NSColor(red: 38/255, green: 166/255, blue: 154/255, alpha: 1)
open static let base = NSColor(red: 0/255, green: 150/255, blue: 136/255, alpha: 1)
open static let darken1 = NSColor(red: 0/255, green: 137/255, blue: 123/255, alpha: 1)
open static let darken2 = NSColor(red: 0/255, green: 121/255, blue: 107/255, alpha: 1)
open static let darken3 = NSColor(red: 0/255, green: 105/255, blue: 92/255, alpha: 1)
open static let darken4 = NSColor(red: 0/255, green: 77/255, blue: 64/255, alpha: 1)
open static let accent1 = NSColor(red: 167/255, green: 255/255, blue: 235/255, alpha: 1)
open static let accent2 = NSColor(red: 100/255, green: 255/255, blue: 218/255, alpha: 1)
open static let accent3 = NSColor(red: 29/255, green: 233/255, blue: 182/255, alpha: 1)
open static let accent4 = NSColor(red: 0/255, green: 191/255, blue: 165/255, alpha: 1)
}
// green
open class green: ColorPalette {
open static let lighten5 = NSColor(red: 232/255, green: 245/255, blue: 233/255, alpha: 1)
open static let lighten4 = NSColor(red: 200/255, green: 230/255, blue: 201/255, alpha: 1)
open static let lighten3 = NSColor(red: 165/255, green: 214/255, blue: 167/255, alpha: 1)
open static let lighten2 = NSColor(red: 129/255, green: 199/255, blue: 132/255, alpha: 1)
open static let lighten1 = NSColor(red: 102/255, green: 187/255, blue: 106/255, alpha: 1)
open static let base = NSColor(red: 76/255, green: 175/255, blue: 80/255, alpha: 1)
open static let darken1 = NSColor(red: 67/255, green: 160/255, blue: 71/255, alpha: 1)
open static let darken2 = NSColor(red: 56/255, green: 142/255, blue: 60/255, alpha: 1)
open static let darken3 = NSColor(red: 46/255, green: 125/255, blue: 50/255, alpha: 1)
open static let darken4 = NSColor(red: 27/255, green: 94/255, blue: 32/255, alpha: 1)
open static let accent1 = NSColor(red: 185/255, green: 246/255, blue: 202/255, alpha: 1)
open static let accent2 = NSColor(red: 105/255, green: 240/255, blue: 174/255, alpha: 1)
open static let accent3 = NSColor(red: 0/255, green: 230/255, blue: 118/255, alpha: 1)
open static let accent4 = NSColor(red: 0/255, green: 200/255, blue: 83/255, alpha: 1)
}
// light green
open class lightGreen: ColorPalette {
open static let lighten5 = NSColor(red: 241/255, green: 248/255, blue: 233/255, alpha: 1)
open static let lighten4 = NSColor(red: 220/255, green: 237/255, blue: 200/255, alpha: 1)
open static let lighten3 = NSColor(red: 197/255, green: 225/255, blue: 165/255, alpha: 1)
open static let lighten2 = NSColor(red: 174/255, green: 213/255, blue: 129/255, alpha: 1)
open static let lighten1 = NSColor(red: 156/255, green: 204/255, blue: 101/255, alpha: 1)
open static let base = NSColor(red: 139/255, green: 195/255, blue: 74/255, alpha: 1)
open static let darken1 = NSColor(red: 124/255, green: 179/255, blue: 66/255, alpha: 1)
open static let darken2 = NSColor(red: 104/255, green: 159/255, blue: 56/255, alpha: 1)
open static let darken3 = NSColor(red: 85/255, green: 139/255, blue: 47/255, alpha: 1)
open static let darken4 = NSColor(red: 51/255, green: 105/255, blue: 30/255, alpha: 1)
open static let accent1 = NSColor(red: 204/255, green: 255/255, blue: 144/255, alpha: 1)
open static let accent2 = NSColor(red: 178/255, green: 255/255, blue: 89/255, alpha: 1)
open static let accent3 = NSColor(red: 118/255, green: 255/255, blue: 3/255, alpha: 1)
open static let accent4 = NSColor(red: 100/255, green: 221/255, blue: 23/255, alpha: 1)
}
// lime
open class lime: ColorPalette {
open static let lighten5 = NSColor(red: 249/255, green: 251/255, blue: 231/255, alpha: 1)
open static let lighten4 = NSColor(red: 240/255, green: 244/255, blue: 195/255, alpha: 1)
open static let lighten3 = NSColor(red: 230/255, green: 238/255, blue: 156/255, alpha: 1)
open static let lighten2 = NSColor(red: 220/255, green: 231/255, blue: 117/255, alpha: 1)
open static let lighten1 = NSColor(red: 212/255, green: 225/255, blue: 87/255, alpha: 1)
open static let base = NSColor(red: 205/255, green: 220/255, blue: 57/255, alpha: 1)
open static let darken1 = NSColor(red: 192/255, green: 202/255, blue: 51/255, alpha: 1)
open static let darken2 = NSColor(red: 175/255, green: 180/255, blue: 43/255, alpha: 1)
open static let darken3 = NSColor(red: 158/255, green: 157/255, blue: 36/255, alpha: 1)
open static let darken4 = NSColor(red: 130/255, green: 119/255, blue: 23/255, alpha: 1)
open static let accent1 = NSColor(red: 244/255, green: 255/255, blue: 129/255, alpha: 1)
open static let accent2 = NSColor(red: 238/255, green: 255/255, blue: 65/255, alpha: 1)
open static let accent3 = NSColor(red: 198/255, green: 255/255, blue: 0/255, alpha: 1)
open static let accent4 = NSColor(red: 174/255, green: 234/255, blue: 0/255, alpha: 1)
}
// yellow
open class yellow: ColorPalette {
open static let lighten5 = NSColor(red: 255/255, green: 253/255, blue: 231/255, alpha: 1)
open static let lighten4 = NSColor(red: 255/255, green: 249/255, blue: 196/255, alpha: 1)
open static let lighten3 = NSColor(red: 255/255, green: 245/255, blue: 157/255, alpha: 1)
open static let lighten2 = NSColor(red: 255/255, green: 241/255, blue: 118/255, alpha: 1)
open static let lighten1 = NSColor(red: 255/255, green: 238/255, blue: 88/255, alpha: 1)
open static let base = NSColor(red: 255/255, green: 235/255, blue: 59/255, alpha: 1)
open static let darken1 = NSColor(red: 253/255, green: 216/255, blue: 53/255, alpha: 1)
open static let darken2 = NSColor(red: 251/255, green: 192/255, blue: 45/255, alpha: 1)
open static let darken3 = NSColor(red: 249/255, green: 168/255, blue: 37/255, alpha: 1)
open static let darken4 = NSColor(red: 245/255, green: 127/255, blue: 23/255, alpha: 1)
open static let accent1 = NSColor(red: 255/255, green: 255/255, blue: 141/255, alpha: 1)
open static let accent2 = NSColor(red: 255/255, green: 255/255, blue: 0/255, alpha: 1)
open static let accent3 = NSColor(red: 255/255, green: 234/255, blue: 0/255, alpha: 1)
open static let accent4 = NSColor(red: 255/255, green: 214/255, blue: 0/255, alpha: 1)
}
// amber
open class amber: ColorPalette {
open static let lighten5 = NSColor(red: 255/255, green: 248/255, blue: 225/255, alpha: 1)
open static let lighten4 = NSColor(red: 255/255, green: 236/255, blue: 179/255, alpha: 1)
open static let lighten3 = NSColor(red: 255/255, green: 224/255, blue: 130/255, alpha: 1)
open static let lighten2 = NSColor(red: 255/255, green: 213/255, blue: 79/255, alpha: 1)
open static let lighten1 = NSColor(red: 255/255, green: 202/255, blue: 40/255, alpha: 1)
open static let base = NSColor(red: 255/255, green: 193/255, blue: 7/255, alpha: 1)
open static let darken1 = NSColor(red: 255/255, green: 179/255, blue: 0/255, alpha: 1)
open static let darken2 = NSColor(red: 255/255, green: 160/255, blue: 0/255, alpha: 1)
open static let darken3 = NSColor(red: 255/255, green: 143/255, blue: 0/255, alpha: 1)
open static let darken4 = NSColor(red: 255/255, green: 111/255, blue: 0/255, alpha: 1)
open static let accent1 = NSColor(red: 255/255, green: 229/255, blue: 127/255, alpha: 1)
open static let accent2 = NSColor(red: 255/255, green: 215/255, blue: 64/255, alpha: 1)
open static let accent3 = NSColor(red: 255/255, green: 196/255, blue: 0/255, alpha: 1)
open static let accent4 = NSColor(red: 255/255, green: 171/255, blue: 0/255, alpha: 1)
}
// orange
open class orange: ColorPalette {
open static let lighten5 = NSColor(red: 255/255, green: 243/255, blue: 224/255, alpha: 1)
open static let lighten4 = NSColor(red: 255/255, green: 224/255, blue: 178/255, alpha: 1)
open static let lighten3 = NSColor(red: 255/255, green: 204/255, blue: 128/255, alpha: 1)
open static let lighten2 = NSColor(red: 255/255, green: 183/255, blue: 77/255, alpha: 1)
open static let lighten1 = NSColor(red: 255/255, green: 167/255, blue: 38/255, alpha: 1)
open static let base = NSColor(red: 255/255, green: 152/255, blue: 0/255, alpha: 1)
open static let darken1 = NSColor(red: 251/255, green: 140/255, blue: 0/255, alpha: 1)
open static let darken2 = NSColor(red: 245/255, green: 124/255, blue: 0/255, alpha: 1)
open static let darken3 = NSColor(red: 239/255, green: 108/255, blue: 0/255, alpha: 1)
open static let darken4 = NSColor(red: 230/255, green: 81/255, blue: 0/255, alpha: 1)
open static let accent1 = NSColor(red: 255/255, green: 209/255, blue: 128/255, alpha: 1)
open static let accent2 = NSColor(red: 255/255, green: 171/255, blue: 64/255, alpha: 1)
open static let accent3 = NSColor(red: 255/255, green: 145/255, blue: 0/255, alpha: 1)
open static let accent4 = NSColor(red: 255/255, green: 109/255, blue: 0/255, alpha: 1)
}
// deep orange
open class deepOrange: ColorPalette {
open static let lighten5 = NSColor(red: 251/255, green: 233/255, blue: 231/255, alpha: 1)
open static let lighten4 = NSColor(red: 255/255, green: 204/255, blue: 188/255, alpha: 1)
open static let lighten3 = NSColor(red: 255/255, green: 171/255, blue: 145/255, alpha: 1)
open static let lighten2 = NSColor(red: 255/255, green: 138/255, blue: 101/255, alpha: 1)
open static let lighten1 = NSColor(red: 255/255, green: 112/255, blue: 67/255, alpha: 1)
open static let base = NSColor(red: 255/255, green: 87/255, blue: 34/255, alpha: 1)
open static let darken1 = NSColor(red: 244/255, green: 81/255, blue: 30/255, alpha: 1)
open static let darken2 = NSColor(red: 230/255, green: 74/255, blue: 25/255, alpha: 1)
open static let darken3 = NSColor(red: 216/255, green: 67/255, blue: 21/255, alpha: 1)
open static let darken4 = NSColor(red: 191/255, green: 54/255, blue: 12/255, alpha: 1)
open static let accent1 = NSColor(red: 255/255, green: 158/255, blue: 128/255, alpha: 1)
open static let accent2 = NSColor(red: 255/255, green: 110/255, blue: 64/255, alpha: 1)
open static let accent3 = NSColor(red: 255/255, green: 61/255, blue: 0/255, alpha: 1)
open static let accent4 = NSColor(red: 221/255, green: 44/255, blue: 0/255, alpha: 1)
}
// brown
open class brown: ColorPalette {
open static let lighten5 = NSColor(red: 239/255, green: 235/255, blue: 233/255, alpha: 1)
open static let lighten4 = NSColor(red: 215/255, green: 204/255, blue: 200/255, alpha: 1)
open static let lighten3 = NSColor(red: 188/255, green: 170/255, blue: 164/255, alpha: 1)
open static let lighten2 = NSColor(red: 161/255, green: 136/255, blue: 127/255, alpha: 1)
open static let lighten1 = NSColor(red: 141/255, green: 110/255, blue: 99/255, alpha: 1)
open static let base = NSColor(red: 121/255, green: 85/255, blue: 72/255, alpha: 1)
open static let darken1 = NSColor(red: 109/255, green: 76/255, blue: 65/255, alpha: 1)
open static let darken2 = NSColor(red: 93/255, green: 64/255, blue: 55/255, alpha: 1)
open static let darken3 = NSColor(red: 78/255, green: 52/255, blue: 46/255, alpha: 1)
open static let darken4 = NSColor(red: 62/255, green: 39/255, blue: 35/255, alpha: 1)
}
// grey
open class grey: ColorPalette {
open static let lighten5 = NSColor(red: 250/255, green: 250/255, blue: 250/255, alpha: 1)
open static let lighten4 = NSColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1)
open static let lighten3 = NSColor(red: 238/255, green: 238/255, blue: 238/255, alpha: 1)
open static let lighten2 = NSColor(red: 224/255, green: 224/255, blue: 224/255, alpha: 1)
open static let lighten1 = NSColor(red: 189/255, green: 189/255, blue: 189/255, alpha: 1)
open static let base = NSColor(red: 158/255, green: 158/255, blue: 158/255, alpha: 1)
open static let darken1 = NSColor(red: 117/255, green: 117/255, blue: 117/255, alpha: 1)
open static let darken2 = NSColor(red: 97/255, green: 97/255, blue: 97/255, alpha: 1)
open static let darken3 = NSColor(red: 66/255, green: 66/255, blue: 66/255, alpha: 1)
open static let darken4 = NSColor(red: 33/255, green: 33/255, blue: 33/255, alpha: 1)
}
// blue grey
open class blueGrey: ColorPalette {
open static let lighten5 = NSColor(red: 236/255, green: 239/255, blue: 241/255, alpha: 1)
open static let lighten4 = NSColor(red: 207/255, green: 216/255, blue: 220/255, alpha: 1)
open static let lighten3 = NSColor(red: 176/255, green: 190/255, blue: 197/255, alpha: 1)
open static let lighten2 = NSColor(red: 144/255, green: 164/255, blue: 174/255, alpha: 1)
open static let lighten1 = NSColor(red: 120/255, green: 144/255, blue: 156/255, alpha: 1)
open static let base = NSColor(red: 96/255, green: 125/255, blue: 139/255, alpha: 1)
open static let darken1 = NSColor(red: 84/255, green: 110/255, blue: 122/255, alpha: 1)
open static let darken2 = NSColor(red: 69/255, green: 90/255, blue: 100/255, alpha: 1)
open static let darken3 = NSColor(red: 55/255, green: 71/255, blue: 79/255, alpha: 1)
open static let darken4 = NSColor(red: 38/255, green: 50/255, blue: 56/255, alpha: 1)
}
}
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