我正在尝试实现与我的xcode项目中旋转的android原生圈子非常相似的动画
我发现了一个可以达到类似目的的课程
import UIKit
@IBDesignable
class SpinnerView : UIView {
override var layer: CAShapeLayer {
get {
return super.layer as! CAShapeLayer
}
}
override class var layerClass: AnyClass {
return CAShapeLayer.self
}
override func layoutSubviews() {
super.layoutSubviews()
layer.fillColor = nil
layer.strokeColor = UIColor.black.cgColor
layer.lineWidth = 3
setPath()
}
override func didMoveToWindow() {
animate()
}
private func setPath() {
layer.path = UIBezierPath(ovalIn: bounds.insetBy(dx: layer.lineWidth / 2, dy: layer.lineWidth / 2)).cgPath
}
struct Pose {
let secondsSincePriorPose: CFTimeInterval
let start: CGFloat
let length: CGFloat
init(_ secondsSincePriorPose: CFTimeInterval, _ start: CGFloat, _ length: CGFloat) {
self.secondsSincePriorPose = secondsSincePriorPose
self.start = start
self.length = length
}
}
class var poses: [Pose] {
get {
return [
Pose(0.0, 0.000, 0.7),
Pose(0.6, 0.500, 0.5),
Pose(0.6, 1.000, 0.3),
Pose(0.6, 1.500, 0.1),
Pose(0.2, 1.875, 0.1),
Pose(0.2, 2.250, 0.3),
Pose(0.2, 2.625, 0.5),
Pose(0.2, 3.000, 0.7),
]
}
}
func animate() {
var time: CFTimeInterval = 0
var times = [CFTimeInterval]()
var start: CGFloat = 0
var rotations = [CGFloat]()
var strokeEnds = [CGFloat]()
let poses = type(of: self).poses
let totalSeconds = poses.reduce(0) { $0 + $1.secondsSincePriorPose }
for pose in poses {
time += pose.secondsSincePriorPose
times.append(time / totalSeconds)
start = pose.start
rotations.append(start * 2 * .pi)
strokeEnds.append(pose.length)
}
times.append(times.last!)
rotations.append(rotations[0])
strokeEnds.append(strokeEnds[0])
animateKeyPath(keyPath: "strokeEnd", duration: totalSeconds, times: times, values: strokeEnds)
animateKeyPath(keyPath: "transform.rotation", duration: totalSeconds, times: times, values: rotations)
animateStrokeHueWithDuration(duration: totalSeconds * 5)
}
func animateKeyPath(keyPath: String, duration: CFTimeInterval, times: [CFTimeInterval], values: [CGFloat]) {
let animation = CAKeyframeAnimation(keyPath: keyPath)
animation.keyTimes = times as [NSNumber]?
animation.values = values
// animation.calculationMode = .linear
animation.duration = duration
animation.repeatCount = Float.infinity
layer.add(animation, forKey: animation.keyPath)
}
func animateStrokeHueWithDuration(duration: CFTimeInterval) {
let count = 36
let animation = CAKeyframeAnimation(keyPath: "strokeColor")
animation.keyTimes = (0 ... count).map { NSNumber(value: CFTimeInterval($0) / CFTimeInterval(count)) }
animation.values = (0 ... count).map {
UIColor(hue: CGFloat($0) / CGFloat(count), saturation: 1, brightness: 1, alpha: 1).cgColor
}
animation.duration = duration
// animation.calculationMode = .linear
animation.repeatCount = Float.infinity
layer.add(animation, forKey: animation.keyPath)
}
}
我的问题是我该如何实际使用该动画在视图控制器中显示它? 甚至可能引导我去某个地方研究
答案 0 :(得分:0)
关于使用这个确切的类,您可以在视图控制器类中进行
class MyViewController: UIViewController
{
override func viewDidLoad()
{
showSpinnerView()
}
func showSpinnerView()
{
let spinnerView = SpinnerView(frame: CGRect(x: 0, y: 0, width:100, height: 100))
self.view.addSubView(view: spinnerView)
}
}
这会将微调器视图添加到ViewControllers视图。在初始化SpinnerView
时创建的CGRect必须是您想要的东西所在的区域,但这是如何创建并将其添加到视图中的方法
在此示例中,视图加载后立即调用show spinner view,但我假设您触发了一些需要加载类型动画的事件,在本例中为您的spinner,因此仅在此处调用show spinner view。
或者,您可以将其添加到视图控制器视图中,因为视图确实加载并设置了spinnerView.isHidden = true
,然后在发生事件时,您只想设置spinnerView.isHidden = false
来显示进度条(显然是在在这种情况下,spinnerView
必须是一个成员变量,以便您可以从其他函数访问其属性