Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 17 additions & 0 deletions Animation-iOS/Animation-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
CA4C8DD32EF02B2D004FDBB5 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = CA4C8DD22EF02B2D004FDBB5 /* Then */; };
CA54AA7D2EB8B1040073AAE1 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = CA54AA7C2EB8B1040073AAE1 /* SnapKit */; };
CA54AA862EB8D3300073AAE1 /* Toast in Frameworks */ = {isa = PBXBuildFile; productRef = CA54AA852EB8D3300073AAE1 /* Toast */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -42,6 +43,7 @@
buildActionMask = 2147483647;
files = (
CA54AA862EB8D3300073AAE1 /* Toast in Frameworks */,
CA4C8DD32EF02B2D004FDBB5 /* Then in Frameworks */,
CA54AA7D2EB8B1040073AAE1 /* SnapKit in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -87,6 +89,7 @@
packageProductDependencies = (
CA54AA7C2EB8B1040073AAE1 /* SnapKit */,
CA54AA852EB8D3300073AAE1 /* Toast */,
CA4C8DD22EF02B2D004FDBB5 /* Then */,
);
productName = "Animation-iOS";
productReference = CA54AA5F2EB8AF930073AAE1 /* Animation-iOS.app */;
Expand Down Expand Up @@ -119,6 +122,7 @@
packageReferences = (
CA54AA7B2EB8B1040073AAE1 /* XCRemoteSwiftPackageReference "SnapKit" */,
CA54AA842EB8D3300073AAE1 /* XCRemoteSwiftPackageReference "Toast-Swift" */,
CA4C8DD12EF02B2D004FDBB5 /* XCRemoteSwiftPackageReference "Then" */,
);
preferredProjectObjectVersion = 77;
productRefGroup = CA54AA602EB8AF930073AAE1 /* Products */;
Expand Down Expand Up @@ -358,6 +362,14 @@
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
CA4C8DD12EF02B2D004FDBB5 /* XCRemoteSwiftPackageReference "Then" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/devxoul/Then";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 3.0.0;
};
};
CA54AA7B2EB8B1040073AAE1 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SnapKit/SnapKit";
Expand All @@ -377,6 +389,11 @@
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
CA4C8DD22EF02B2D004FDBB5 /* Then */ = {
isa = XCSwiftPackageProductDependency;
package = CA4C8DD12EF02B2D004FDBB5 /* XCRemoteSwiftPackageReference "Then" */;
productName = Then;
};
CA54AA7C2EB8B1040073AAE1 /* SnapKit */ = {
isa = XCSwiftPackageProductDependency;
package = CA54AA7B2EB8B1040073AAE1 /* XCRemoteSwiftPackageReference "SnapKit" */;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
79 changes: 79 additions & 0 deletions Animation-iOS/Animation-iOS/ProgressBarView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import UIKit

final class ProgressBarView: UIView {

// MARK: - Properties

private var circleLayer = CAShapeLayer()
private var progressLayer = CAShapeLayer()


private var startPoint = CGFloat(3 * Double.pi / 4)

private var endPoint = CGFloat(Double.pi / 4)

// MARK: - Drawing

override func draw(_ rect: CGRect) {
createCircularPath()
}

// MARK: - Private Methods


private func createCircularPath() {
self.backgroundColor = .white


let path = UIBezierPath(
arcCenter: CGPoint(x: self.frame.width / 2,
y: self.frame.height / 2),
radius: (frame.size.height - 10) / 2,
startAngle: startPoint,
endAngle: endPoint,
clockwise: true
)


circleLayer.path = path.cgPath
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineCap = .round
circleLayer.lineWidth = 10
circleLayer.strokeEnd = 1
circleLayer.strokeColor = UIColor.black.withAlphaComponent(0.4).cgColor
layer.addSublayer(circleLayer)


progressLayer.path = path.cgPath
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.lineCap = .round
progressLayer.lineWidth = 10
progressLayer.strokeEnd = 0
progressLayer.strokeColor = UIColor.systemRed.cgColor
layer.addSublayer(progressLayer)
}

// MARK: - Public Methods


func progressAnimation(duration: TimeInterval, value: Double) {

let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")
circularProgressAnimation.duration = duration


circularProgressAnimation.toValue = value


circularProgressAnimation.fillMode = .forwards
circularProgressAnimation.isRemovedOnCompletion = false

progressLayer.add(circularProgressAnimation, forKey: "progressAnim")
}


func resetProgress() {
progressLayer.removeAnimation(forKey: "progressAnim")
progressLayer.strokeEnd = 0
}
}
127 changes: 127 additions & 0 deletions Animation-iOS/Animation-iOS/ProgressBarViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import UIKit
import SnapKit
import Then

final class ProgressBarViewController: UIViewController {

// MARK: - UI Components

private let fullCircleView = FullCircleProgressView()
private let semiCircleView = SemiCircleProgressView()
private let linearView = LinearProgressView()

private let label1 = UILabel()
private let label2 = UILabel()
private let label3 = UILabel()

private let startButton = UIButton(type: .system)

// MARK: - Lifecycle

override func viewDidLoad() {
super.viewDidLoad()

setStyle()
setHierarchy()
setLayout()
setTarget()
}

// MARK: - Setup

private func setStyle() {
view.backgroundColor = .white
title = "Progress Bar"

label1.do {
$0.text = "완전한 원"
$0.font = .systemFont(ofSize: 14)
$0.textAlignment = .center
}

label2.do {
$0.text = "반원"
$0.font = .systemFont(ofSize: 14)
$0.textAlignment = .center
}

label3.do {
$0.text = "직선 바"
$0.font = .systemFont(ofSize: 14)
$0.textAlignment = .center
}

startButton.do {
$0.setTitle("Start All", for: .normal)
$0.titleLabel?.font = .systemFont(ofSize: 18, weight: .semibold)
$0.backgroundColor = .systemBlue
$0.setTitleColor(.white, for: .normal)
$0.layer.cornerRadius = 12
}
}

private func setHierarchy() {
[fullCircleView, semiCircleView, linearView,
label1, label2, label3, startButton].forEach {
view.addSubview($0)
}
}

private func setLayout() {
fullCircleView.snp.makeConstraints {
$0.top.equalTo(view.safeAreaLayoutGuide).offset(40)
$0.centerX.equalToSuperview()
$0.size.equalTo(120)
}

label1.snp.makeConstraints {
$0.top.equalTo(fullCircleView.snp.bottom).offset(8)
$0.centerX.equalToSuperview()
}

semiCircleView.snp.makeConstraints {
$0.top.equalTo(label1.snp.bottom).offset(30)
$0.centerX.equalToSuperview()
$0.size.equalTo(120)
}

label2.snp.makeConstraints {
$0.top.equalTo(semiCircleView.snp.bottom).offset(8)
$0.centerX.equalToSuperview()
}

linearView.snp.makeConstraints {
$0.top.equalTo(label2.snp.bottom).offset(30)
$0.leading.trailing.equalToSuperview().inset(40)
$0.height.equalTo(30)
}

label3.snp.makeConstraints {
$0.top.equalTo(linearView.snp.bottom).offset(8)
$0.centerX.equalToSuperview()
}

startButton.snp.makeConstraints {
$0.top.equalTo(label3.snp.bottom).offset(40)
$0.centerX.equalToSuperview()
$0.width.equalTo(150)
$0.height.equalTo(50)
}
}

private func setTarget() {
startButton.addTarget(self, action: #selector(startButtonTapped), for: .touchUpInside)
}

// MARK: - Actions

@objc private func startButtonTapped() {
fullCircleView.progressAnimation(duration: 2.0, value: 0.75)
semiCircleView.progressAnimation(duration: 2.0, value: 0.75)
linearView.progressAnimation(duration: 2.0, value: 0.75)
}
}

#Preview {
ProgressBarViewController()
}
Loading