[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce idea of a TimingFunction #83

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Sources/Classes/Full View/DefaultFullViewAnimations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public extension Spruce {
/// - animationType: style of animation that each view should follow. Don't worry about setting the `changeFunction`. We will set that using the stock animations that you provide. If you have a value there it will be overwritten. (ex: SpringAnimation)
/// - completion: a closure that is called upon the final animation completing. A `Bool` is passed into the closure letting you know if the animation has completed. **Note:** If you stop animations on the whole animating view, then `false` will be passed into the completion closure. However, if the final animation is allowed to proceed then `true` will be the value passed into the completion closure.
public func animate(_ animations: [StockAnimation], duration: TimeInterval = 0.3, animationType: Animation, completion: CompletionHandler? = nil) {
let sortFunction = LinearSortFunction(direction: .topToBottom, interObjectDelay: 0.05)
let sortFunction = LinearSortFunction(direction: .topToBottom)
self.animate(animations, duration: duration, animationType: animationType, sortFunction: sortFunction, completion: completion)
}

Expand All @@ -104,7 +104,8 @@ public extension Spruce {
animationFunc(view)
}
}
self.animate(withSortFunction: sortFunction, animation: animationType, completion: completion)
let timingFunction = InterItemTimingFunction(interObjectDelay: 0.1)
self.animate(withSortFunction: sortFunction, timingFunction: timingFunction, animation: animationType, completion: completion)
}

/// Use this method to setup all of your views before the animation occurs. This could include hiding, fading, translating them, etc...
Expand Down
5 changes: 3 additions & 2 deletions Sources/Classes/Full View/FullViewAnimation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ public extension Spruce {
/// - exclude: an array of views that the animation should skip over
/// - recursiveDepth: an int describing how deep into the view hiearchy the subview search should go, defaults to 0
/// - completion: a closure that is called upon the final animation completing. A `Bool` is passed into the closure letting you know if the animation has completed. **Note:** If you stop animations on the whole animating view, then `false` will be passed into the completion closure. However, if the final animation is allowed to proceed then `true` will be the value passed into the completion closure.
public func animate(withSortFunction sortFunction: SortFunction, prepare: PrepareHandler? = nil, animation: Animation, exclude: [UIView]? = nil, recursiveDepth: Int = 0, completion: CompletionHandler? = nil) {
var timedViews = sortFunction.timeOffsets(view: self.view, recursiveDepth: recursiveDepth)
public func animate(withSortFunction sortFunction: SortFunction, timingFunction: TimingFunction, prepare: PrepareHandler? = nil, animation: Animation, exclude: [UIView]? = nil, recursiveDepth: Int = 0, completion: CompletionHandler? = nil) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The curse of good documentation — you need to update the parameter above.

let weightedViews = sortFunction.weights(forView: self.view, recursiveDepth: recursiveDepth)
var timedViews = timingFunction.timeOffsets(forViews: weightedViews)
timedViews = timedViews.sorted { (left, right) -> Bool in
return left.timeOffset < right.timeOffset
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Classes/Full View/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ open class ViewController: UIViewController {

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
animationType = StandardAnimation(duration: duration)
sortFunction = LinearSortFunction(direction: .topToBottom, interObjectDelay: 0.05)
sortFunction = LinearSortFunction(direction: .topToBottom)
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

Expand Down
72 changes: 0 additions & 72 deletions Sources/Classes/Sort Functions/ContinuousSortFunction.swift

This file was deleted.

43 changes: 14 additions & 29 deletions Sources/Classes/Sort Functions/ContinuousWeightedSortFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,41 +45,26 @@ public struct ContinuousWeightedSortFunction: PositionSortFunction, WeightSortFu
self.position = position
self.duration = duration
}

public func timeOffsets(view: UIView, recursiveDepth: Int) -> [TimedView] {
public func weights(forView view: UIView, recursiveDepth: Int) -> [WeightedView] {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weights(for view: UIView... is probably slightly more idiomatic naming.

let subviews = view.spruce.subviews(withRecursiveDepth: recursiveDepth)
let comparisonPoint = distancePoint(view: view, subviews: subviews)

let distancedViews = subviews.map {
return (view: $0, horizontalDistance: comparisonPoint.spruce.horizontalDistance(to: $0.referencePoint) * horizontalWeight.coefficient, verticalDistance: comparisonPoint.spruce.verticalDistance(to: $0.referencePoint) * verticalWeight.coefficient)
}

guard let maxHorizontalDistance = distancedViews.max(by: { $0.horizontalDistance < $1.horizontalDistance })?.horizontalDistance, let maxVerticalDistance = distancedViews.max(by: { $0.verticalDistance < $1.verticalDistance })?.verticalDistance, maxHorizontalDistance > 0.0, maxVerticalDistance > 0.0 else {
return []
}

var timedViews: [TimedView] = []
var maxTimeOffset: TimeInterval = 0.0
for view in distancedViews {
let normalizedHorizontalDistance = view.horizontalDistance / maxHorizontalDistance
let normalizedVerticalDistance = view.verticalDistance / maxVerticalDistance
let offset = duration * (normalizedHorizontalDistance * horizontalWeight.coefficient + normalizedVerticalDistance * verticalWeight.coefficient)
if offset > maxTimeOffset {
maxTimeOffset = offset
}
let timedView = TimedView(spruceView: view.view, timeOffset: offset)
timedViews.append(timedView)
var maxWeight: Double = 0.0

let weightedViews: [WeightedView] = subviews.map {
let horizontalDistance = comparisonPoint.spruce.horizontalDistance(to: $0.referencePoint) * horizontalWeight.coefficient
let verticalDistance = comparisonPoint.spruce.verticalDistance(to: $0.referencePoint) * verticalWeight.coefficient
let distance = horizontalDistance + verticalDistance
maxWeight = max(maxWeight, distance)
return WeightedView(spruceView: $0, weight: distance)
}

for index in 0..<timedViews.count {
let timeOffset = timedViews[index].timeOffset
let normalizedTimeOffset = (timeOffset / maxTimeOffset) * duration
timedViews[index].timeOffset = normalizedTimeOffset
if reversed {
timedViews[index].timeOffset = duration - normalizedTimeOffset
if reversed {
for var weightedView in weightedViews {
weightedView.weight = maxWeight - weightedView.weight
}
}

return timedViews
return weightedViews
}
}
21 changes: 21 additions & 0 deletions Sources/Classes/Sort Functions/CorneredSortFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,27 @@ public struct CorneredSortFunction: CornerSortFunction {
return timedViews
}

public func weights(forView view: UIView, recursiveDepth: Int) -> [WeightedView] {
let comparisonPoint = distancePoint(view: view)
let subviews = view.spruce.subviews(withRecursiveDepth: recursiveDepth)

var maxWeight: Double = 0.0

let weightedViews: [WeightedView] = subviews.map {
let distance = Double(abs(comparisonPoint.x - $0.referencePoint.x) + abs(comparisonPoint.y - $0.referencePoint.y))
maxWeight = max(maxWeight, distance)
return WeightedView(spruceView: $0, weight: distance)
}

if reversed {
for var weightedView in weightedViews {
weightedView.weight = maxWeight - weightedView.weight
}
}

return weightedViews
}

public func distancePoint(view: UIView, subviews: [View] = []) -> CGPoint {
let distancePoint: CGPoint
let bounds = view.bounds
Expand Down
22 changes: 8 additions & 14 deletions Sources/Classes/Sort Functions/DefaultSortFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,19 @@ import UIKit
/// The basic `SortFunction`. Use this sort function if you want to animate in all views at the same time and give an `interObjectDelay` of `0.0`. Note that this `SortFunction` will animate the views based on the order they were added to the animation view. This means that the way the views are sorted in the `subviews` array is the way that they will be sorted by this `SortFunction`.
public struct DefaultSortFunction: SortFunction {

public var interObjectDelay: TimeInterval = 0.0

public init() {

}

public init(interObjectDelay: TimeInterval) {
self.interObjectDelay = interObjectDelay
}

public func timeOffsets(view: UIView, recursiveDepth: Int) -> [TimedView] {
var timedViews: [TimedView] = []
var currentTimeOffset: TimeInterval = 0.0
public func weights(forView view: UIView, recursiveDepth: Int) -> [WeightedView] {
let subviews = view.spruce.subviews(withRecursiveDepth: recursiveDepth)
for subView in subviews {
let timedView = TimedView(spruceView: subView, timeOffset: currentTimeOffset)
timedViews.append(timedView)
currentTimeOffset += interObjectDelay
var currentWeight: Double = 0.0
var weightedViews: [WeightedView] = []
for subview in subviews {
let timedView = WeightedView(spruceView: subview, weight: currentWeight)
weightedViews.append(timedView)
currentWeight += 1.0
}
return timedViews
return weightedViews
}
}
18 changes: 8 additions & 10 deletions Sources/Classes/Sort Functions/InlineSortFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,14 @@ import UIKit
/// - Note: If you set any type of right corner, then the views will enter as if you are reading text from right to left.
public struct InlineSortFunction: CornerSortFunction {

public var interObjectDelay: TimeInterval
public var reversed: Bool = false
public var corner: Corner

public init(corner: Corner, interObjectDelay: TimeInterval) {
public init(corner: Corner) {
self.corner = corner
self.interObjectDelay = interObjectDelay
}

public func timeOffsets(view: UIView, recursiveDepth: Int) -> [TimedView] {
public func weights(forView view: UIView, recursiveDepth: Int) -> [WeightedView] {
let comparisonPoint = distancePoint(view: view)
let subviews = view.spruce.subviews(withRecursiveDepth: recursiveDepth)

Expand All @@ -58,14 +56,14 @@ public struct InlineSortFunction: CornerSortFunction {
distancedViews.reverse()
}

var currentTimeOffset = 0.0
var timedViews: [TimedView] = []
var currentWeight = 0.0
var weightedViews: [WeightedView] = []
for view in distancedViews {
let timedView = TimedView(spruceView: view.view, timeOffset: currentTimeOffset)
timedViews.append(timedView)
currentTimeOffset += interObjectDelay
let timedView = WeightedView(spruceView: view.view, weight: currentWeight)
weightedViews.append(timedView)
currentWeight += 1.0
}

return timedViews
return weightedViews
}
}
4 changes: 1 addition & 3 deletions Sources/Classes/Sort Functions/LinearSortFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ import UIKit
/// A `Linear` wiping `SortFunction`. This will consider the rows or columns of the views rather than looking at their exact coordinates. Views that have the same vertical or horizontal components, based on the `direction`, will animate in at the same time.
public struct LinearSortFunction: DirectionSortFunction {
public var direction: Direction
public var interObjectDelay: TimeInterval
public var reversed: Bool = false

public init(direction: Direction, interObjectDelay: TimeInterval) {
public init(direction: Direction) {
self.direction = direction
self.interObjectDelay = interObjectDelay
}

public func distanceBetween(_ left: CGPoint, and right: CGPoint) -> Double {
Expand Down
Loading