Skip to content

Commit 0a7241d

Browse files
committed
13.8.5
1 parent d90759c commit 0a7241d

29 files changed

+1633
-542
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Change Log
22

3+
## [13.8.5](https://github.com/relatedcode/ProgressHUD/releases/tag/13.8.5)
4+
5+
Released on 2023-10-13.
6+
7+
#### Added
8+
9+
- Introduced 9 new animations to offer a more engaging and visually captivating user experience.
10+
11+
#### Changed
12+
13+
- Refactored existing animation names, including adjustments to the `AnimationType` enum.
14+
- Split the animations-related source files for better maintainability and organization.
15+
- Updated a few of the existing animations in terms of shape, size, and duration.
16+
317
## [13.8.4](https://github.com/relatedcode/ProgressHUD/releases/tag/13.8.4)
418

519
Released on 2023-10-05.

ProgressHUD.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'ProgressHUD'
3-
s.version = '13.8.4'
3+
s.version = '13.8.5'
44
s.license = 'MIT'
55

66
s.summary = 'A lightweight and easy-to-use Progress HUD for iOS.'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// Copyright (c) 2023 Related Code - https://relatedcode.com
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
12+
import UIKit
13+
14+
// MARK: - Activity Indicator
15+
extension ProgressHUD {
16+
17+
func animationActivityIndicator(_ view: UIView, _ color: UIColor) {
18+
let spinner = UIActivityIndicatorView(style: .large)
19+
let scale = view.frame.size.width / spinner.frame.size.width
20+
spinner.transform = CGAffineTransform(scaleX: scale, y: scale)
21+
spinner.frame = view.bounds
22+
spinner.color = color
23+
spinner.hidesWhenStopped = true
24+
spinner.startAnimating()
25+
view.addSubview(spinner)
26+
}
27+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//
2+
// Copyright (c) 2023 Related Code - https://relatedcode.com
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
12+
import UIKit
13+
14+
// MARK: - Ball Vertical Bounce
15+
extension ProgressHUD {
16+
17+
func animationBallVerticalBounce(_ view: UIView, _ color: UIColor) {
18+
let line = CAShapeLayer()
19+
line.strokeColor = color.cgColor
20+
line.lineWidth = view.frame.height / 15
21+
line.lineCap = .round
22+
line.fillColor = UIColor.clear.cgColor
23+
view.layer.addSublayer(line)
24+
let speed = 0.07
25+
26+
let animationDownCurve = CAKeyframeAnimation(keyPath: "path")
27+
animationDownCurve.timingFunction = CAMediaTimingFunction(name: .easeOut)
28+
animationDownCurve.duration = 2.1 * speed
29+
animationDownCurve.values = [initialCurvePath(in: view).cgPath, downCurvePath(in: view).cgPath]
30+
animationDownCurve.autoreverses = true
31+
animationDownCurve.beginTime = 2.9 * speed
32+
33+
let animationTopCurve = CAKeyframeAnimation(keyPath: "path")
34+
animationTopCurve.timingFunction = CAMediaTimingFunction(name: .easeOut)
35+
animationTopCurve.duration = 0.4 * speed
36+
animationTopCurve.values = [initialCurvePath(in: view).cgPath, topCurvePath(in: view).cgPath]
37+
animationTopCurve.autoreverses = true
38+
animationTopCurve.beginTime = 7.1 * speed
39+
40+
let animationGroup = CAAnimationGroup()
41+
animationGroup.animations = [animationDownCurve, animationTopCurve]
42+
animationGroup.duration = 10 * speed
43+
animationGroup.repeatCount = .infinity
44+
45+
line.add(animationGroup, forKey: "pathAnimation")
46+
line.path = initialCurvePath(in: view).cgPath
47+
48+
createBallAnimation(in: view, with: color, speed: speed)
49+
}
50+
51+
private func initialCurvePath(in view: UIView) -> UIBezierPath {
52+
let width = view.frame.size.width
53+
let height = view.frame.size.height + view.frame.size.height / 3
54+
let path = UIBezierPath()
55+
path.move(to: CGPoint(x: 0, y: height / 2))
56+
path.addQuadCurve(to: CGPoint(x: width, y: height / 2), controlPoint: CGPoint(x: width / 2, y: height / 2))
57+
return path
58+
}
59+
60+
private func downCurvePath(in view: UIView) -> UIBezierPath {
61+
let width = view.frame.size.width
62+
let height = view.frame.size.height + view.frame.size.height / 3
63+
let path = UIBezierPath()
64+
path.move(to: CGPoint(x: 0, y: height / 2))
65+
path.addQuadCurve(to: CGPoint(x: width, y: height / 2), controlPoint: CGPoint(x: width / 2, y: height / 1.3))
66+
return path
67+
}
68+
69+
private func topCurvePath(in view: UIView) -> UIBezierPath {
70+
let width = view.frame.size.width
71+
let height = view.frame.size.height + view.frame.size.height / 3
72+
let path = UIBezierPath()
73+
path.move(to: CGPoint(x: 0, y: height / 2))
74+
path.addQuadCurve(to: CGPoint(x: width, y: height / 2), controlPoint: CGPoint(x: width / 2, y: height / 2.3))
75+
return path
76+
}
77+
78+
private func createBallAnimation(in view: UIView, with color: UIColor, speed: Double) {
79+
let width = view.frame.size.width
80+
let height = view.frame.size.height
81+
let size = width / 4
82+
let yPosition = height - height / 3
83+
84+
let circle = drawCircleWith(CGSize(width: size, height: size), color)
85+
circle.frame = CGRect(x: width / 2 - size / 2, y: height / 20, width: size, height: size)
86+
87+
let animation = CABasicAnimation(keyPath: "transform.translation.y")
88+
animation.fromValue = 0
89+
animation.toValue = yPosition - size / 2
90+
animation.duration = 5.0 * speed
91+
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
92+
animation.autoreverses = true
93+
animation.repeatCount = .infinity
94+
95+
circle.add(animation, forKey: "animation")
96+
view.layer.addSublayer(circle)
97+
}
98+
99+
private func drawCircleWith(_ size: CGSize, _ color: UIColor) -> CALayer {
100+
let path = UIBezierPath()
101+
let radius = size.width / 4
102+
let center = CGPoint(x: size.width / 2, y: size.height / 2)
103+
path.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true)
104+
105+
let layer = CAShapeLayer()
106+
layer.fillColor = nil
107+
layer.strokeColor = color.cgColor
108+
layer.lineWidth = size.width / 2
109+
layer.backgroundColor = nil
110+
layer.path = path.cgPath
111+
112+
return layer
113+
}
114+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//
2+
// Copyright (c) 2023 Related Code - https://relatedcode.com
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
12+
import UIKit
13+
14+
// MARK: - Bar Sweep Toggle
15+
extension ProgressHUD {
16+
17+
func animationBarSweepToggle(_ view: UIView, _ color: UIColor) {
18+
let height = view.frame.size.height
19+
let width = view.frame.size.width
20+
21+
let border = 5.0
22+
let duration = 0.9
23+
let heightBar = height / 6
24+
let widthBar = width - heightBar / 2
25+
26+
let pathBar = UIBezierPath()
27+
pathBar.move(to: CGPoint(x: heightBar / 2, y: height / 2))
28+
pathBar.addLine(to: CGPoint(x: widthBar / 2, y: height / 2))
29+
30+
let layerBar = CAShapeLayer()
31+
layerBar.path = pathBar.cgPath
32+
layerBar.strokeColor = color.cgColor
33+
layerBar.lineWidth = heightBar
34+
layerBar.lineCap = .round
35+
view.layer.addSublayer(layerBar)
36+
37+
let animationGroup = CAAnimationGroup()
38+
animationGroup.duration = duration
39+
animationGroup.autoreverses = true
40+
animationGroup.repeatCount = .infinity
41+
42+
let animationStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
43+
animationStrokeEnd.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
44+
animationStrokeEnd.fromValue = 0.0
45+
animationStrokeEnd.toValue = 1.0
46+
animationStrokeEnd.duration = duration / 2
47+
48+
let animationStrokeStart = CABasicAnimation(keyPath: "strokeStart")
49+
animationStrokeStart.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
50+
animationStrokeStart.fromValue = 0.0
51+
animationStrokeStart.toValue = 1.0
52+
animationStrokeStart.duration = duration / 2
53+
animationStrokeStart.beginTime = duration / 2
54+
55+
animationGroup.animations = [animationStrokeEnd, animationStrokeStart]
56+
layerBar.add(animationGroup, forKey: "group")
57+
58+
let animationPosition = CABasicAnimation(keyPath: "transform.translation.x")
59+
animationPosition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
60+
animationPosition.fromValue = 0
61+
animationPosition.toValue = widthBar / 2
62+
animationPosition.duration = duration
63+
animationPosition.autoreverses = true
64+
animationPosition.repeatCount = .infinity
65+
layerBar.add(animationPosition, forKey: "position")
66+
67+
let frame = CGRect(x: -border, y: (height - heightBar) / 2 - border, width: width + 2 * border, height: heightBar + 2 * border)
68+
69+
let pathBorder = UIBezierPath(roundedRect: frame, cornerRadius: height)
70+
let layerBorder = CAShapeLayer()
71+
layerBorder.path = pathBorder.cgPath
72+
layerBorder.strokeColor = color.cgColor
73+
layerBorder.fillColor = UIColor.clear.cgColor
74+
layerBorder.lineWidth = border
75+
view.layer.addSublayer(layerBorder)
76+
}
77+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//
2+
// Copyright (c) 2023 Related Code - https://relatedcode.com
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
12+
import UIKit
13+
14+
// MARK: - Circle Arc Dot Spin
15+
extension ProgressHUD {
16+
17+
func animationCircleArcDotSpin(_ view: UIView, _ color: UIColor) {
18+
let space = view.frame.width / 8
19+
let x = view.bounds.minX + space / 2
20+
let y = view.bounds.minY + space / 2
21+
let width = view.frame.width - space
22+
let height = view.frame.height - space
23+
let containerView = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
24+
view.addSubview(containerView)
25+
26+
let center = CGPoint(x: containerView.bounds.midX, y: containerView.bounds.midY)
27+
let radius = containerView.frame.width / 2
28+
let count = 8
29+
let duration = 4.0
30+
let size = radius / 3
31+
32+
for i in 0..<count {
33+
let angle = (CGFloat(i) / CGFloat(count)) * (2 * .pi)
34+
let x = center.x + radius * cos(angle)
35+
let y = center.y + radius * sin(angle)
36+
37+
let circle = UIView(frame: CGRect(x: x - size / 2, y: y - size / 2, width: size, height: size))
38+
circle.backgroundColor = color
39+
circle.layer.cornerRadius = size / 2
40+
containerView.addSubview(circle)
41+
42+
let animation = CAKeyframeAnimation(keyPath: "position")
43+
animation.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: angle, endAngle: angle + 2 * .pi, clockwise: true).cgPath
44+
animation.duration = duration
45+
animation.repeatCount = .infinity
46+
animation.calculationMode = .paced
47+
circle.layer.add(animation, forKey: "circleAnimation")
48+
}
49+
50+
animateArcRotation(containerView, color)
51+
}
52+
53+
private func animateArcRotation(_ view: UIView, _ color: UIColor) {
54+
let width = view.frame.size.width
55+
let height = view.frame.size.height
56+
let center = CGPoint(x: width / 2, y: height / 2)
57+
58+
let animationRotation = CABasicAnimation(keyPath: "transform.rotation")
59+
animationRotation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
60+
animationRotation.byValue = 4 * Float.pi
61+
animationRotation.duration = 1.6
62+
63+
let animationStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
64+
animationStrokeEnd.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
65+
animationStrokeEnd.fromValue = 0.5
66+
animationStrokeEnd.toValue = 1
67+
animationStrokeEnd.duration = 0.8
68+
animationStrokeEnd.autoreverses = true
69+
animationStrokeEnd.isRemovedOnCompletion = false
70+
71+
let animationGroup = CAAnimationGroup()
72+
animationGroup.animations = [animationRotation, animationStrokeEnd]
73+
animationGroup.duration = 1.6
74+
animationGroup.repeatCount = .infinity
75+
animationGroup.fillMode = .forwards
76+
77+
let path = UIBezierPath(arcCenter: center, radius: width / 2, startAngle: -.pi / 2, endAngle: 0, clockwise: true)
78+
79+
let layer = CAShapeLayer()
80+
layer.frame = CGRect(x: 0, y: 0, width: width, height: height)
81+
layer.path = path.cgPath
82+
layer.fillColor = nil
83+
layer.strokeColor = color.cgColor
84+
layer.lineWidth = view.frame.width / 6
85+
layer.lineCap = .round
86+
87+
layer.add(animationGroup, forKey: "animation")
88+
view.layer.addSublayer(layer)
89+
}
90+
}

0 commit comments

Comments
 (0)