UIView animate - 旋转并放大,然后旋转并缩小
UIView animate - Rotate and scale up, then rotate and scale down
我有一个子类图像视图,我想淡入、放大和旋转,然后在缩小和淡出的同时继续旋转。
我正在使用带有完成处理程序的 UIView 动画块来处理收缩。
问题是它不是流畅的动画。在完成处理程序运行之前,动画再次在 运行 之前停止。我需要它成为一个不错的 "swoop" 动画。
代码如下:
let duration: TimeInterval = 3.0
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
UIView.animate(withDuration: duration * 3, delay: 0, options: [.curveLinear], animations: {
// initial transform
self.alpha = 0
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// initial spin for duration of animaton
UIView.animate(withDuration: duration * 3, delay: 0.0, options: [.curveLinear], animations: {
self.transform = rotate
}, completion: nil)
// scaling and fading
UIView.animate(withDuration: duration, delay: 0, options: [.curveLinear], animations: {
UIView.setAnimationRepeatCount(3)
self.transform = self.transform.scaledBy(x: 0.8, y: 0.8)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration: duration, animations: {
UIView.setAnimationRepeatCount(3)
self.transform = self.transform.scaledBy(x: 0.1, y: 0.1)
self.alpha = 0
})
}
}, completion: nil)
如何让动画在整个时间旋转,同时淡入和放大,然后再缩小和淡出?整个动画应持续 3 秒,并重复 3 次。谢谢
尝试使用 CGAffineTransformConcat()
CGAffineTransform scale = CGAffineTransformMakeScale(0.8, 0.8);
self.transform = CGAffineTransformConcat(CGAffineTransformRotate(self.transform, M_PI / 2), scale);
我看到 onCompletion 开始时旋转有轻微的卡顿。
我使用您的代码创建了一个缩减(如下面的蓝色视图所示)和橙色视图中的一个变体。这是从模拟器上拿来的,变成了动画GIF,所以速度变慢了。橙色视图继续旋转,因为完整的变换只是按比例缩小。
这是橙色视图的 layoutSubviews() 的代码
override func layoutSubviews() {
super.layoutSubviews()
let duration: TimeInterval = 3.0
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
// initial transform
self.alpha = 0
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// initial spin for duration of animaton
UIView.animate(withDuration: duration,
delay: 0.0,
options: [.curveLinear],
animations: {
self.transform = rotate;
},
completion: nil)
// scaling and fading
UIView.animate(withDuration: duration/2.0, animations: {
self.transform = self.transform.scaledBy(x: 0.8, y: 0.8)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration: duration/2.0, animations: {
self.transform = self.transform.scaledBy(x: 0.1, y: 0.1)
self.alpha = 0
})
}
}
根据您修改后的要求,我正在使用块动画扩展您已经看到的内容。正如一些人所说,无论如何,关键帧动画可能会更好,这是我的想法。
创建一个通过变换视图来旋转整个时间的动画。
创建另一个基于当前变换(正在旋转)进行缩放和淡入淡出的动画。在此过程中,我刚刚创建了一些变量以允许您自定义(和重复)动画的某些部分。为了清楚起见,我打破了一些东西,并且知道我可以重构以写得更简洁。
这是代码
import UIKit
class OrangeView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
let duration: TimeInterval = 9.0
self.transform = CGAffineTransform.identity
// initial transform
self.alpha = 1
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// start rotation
rotate(duration: duration)
// scaling and fading
scaleUpAndDown(desiredRepetitions: 3, initalDuration: duration)
}
func rotate(duration: TimeInterval) {
UIView.animate(withDuration: duration/2.0,
delay: 0.0,
options: [.curveLinear], animations: {
let angle = Double.pi
self.transform = self.transform.rotated(by: CGFloat(angle))
}, completion: {[weak self] finished in
guard let strongSelf = self else {
return
}
if finished &&
strongSelf.transform != CGAffineTransform.identity {
strongSelf.rotate(duration: duration)
} else {
// rotation ending
}
})
}
func scaleUpAndDown(timesRepeated: Int = 0, desiredRepetitions: Int, initalDuration: TimeInterval) {
guard timesRepeated < desiredRepetitions,
desiredRepetitions > 0, initalDuration > 0 else {
self.transform = CGAffineTransform.identity
return
}
let repeatedCount = timesRepeated + 1
let scalingDuration = initalDuration/2.0/Double(desiredRepetitions)
UIView.animate(withDuration: scalingDuration,
delay: 0.0,
animations: {
let desiredOriginalScale: CGFloat = 0.8
let scaleX = abs(CGAffineTransform.identity.a / self.transform.a) * desiredOriginalScale
let scaleY = abs(CGAffineTransform.identity.d / self.transform.d) * desiredOriginalScale
self.transform = self.transform.scaledBy(x: scaleX, y: scaleY)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration:scalingDuration,
delay: 0.0,
animations: {
let desiredOriginalScale: CGFloat = 0.1
let scaleX = abs(CGAffineTransform.identity.a / self.transform.a) * desiredOriginalScale
let scaleY = abs(CGAffineTransform.identity.d / self.transform.d) * desiredOriginalScale
self.transform = self.transform.scaledBy(x: scaleX, y: scaleY)
self.alpha = 0
}) { finshed in
self.scaleUpAndDown(timesRepeated: repeatedCount, desiredRepetitions: desiredRepetitions, initalDuration: initalDuration);
}
}
}
}
终于来一张gif动图
我有一个子类图像视图,我想淡入、放大和旋转,然后在缩小和淡出的同时继续旋转。
我正在使用带有完成处理程序的 UIView 动画块来处理收缩。
问题是它不是流畅的动画。在完成处理程序运行之前,动画再次在 运行 之前停止。我需要它成为一个不错的 "swoop" 动画。
代码如下:
let duration: TimeInterval = 3.0
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
UIView.animate(withDuration: duration * 3, delay: 0, options: [.curveLinear], animations: {
// initial transform
self.alpha = 0
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// initial spin for duration of animaton
UIView.animate(withDuration: duration * 3, delay: 0.0, options: [.curveLinear], animations: {
self.transform = rotate
}, completion: nil)
// scaling and fading
UIView.animate(withDuration: duration, delay: 0, options: [.curveLinear], animations: {
UIView.setAnimationRepeatCount(3)
self.transform = self.transform.scaledBy(x: 0.8, y: 0.8)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration: duration, animations: {
UIView.setAnimationRepeatCount(3)
self.transform = self.transform.scaledBy(x: 0.1, y: 0.1)
self.alpha = 0
})
}
}, completion: nil)
如何让动画在整个时间旋转,同时淡入和放大,然后再缩小和淡出?整个动画应持续 3 秒,并重复 3 次。谢谢
尝试使用 CGAffineTransformConcat()
CGAffineTransform scale = CGAffineTransformMakeScale(0.8, 0.8);
self.transform = CGAffineTransformConcat(CGAffineTransformRotate(self.transform, M_PI / 2), scale);
我看到 onCompletion 开始时旋转有轻微的卡顿。
我使用您的代码创建了一个缩减(如下面的蓝色视图所示)和橙色视图中的一个变体。这是从模拟器上拿来的,变成了动画GIF,所以速度变慢了。橙色视图继续旋转,因为完整的变换只是按比例缩小。
这是橙色视图的 layoutSubviews() 的代码
override func layoutSubviews() {
super.layoutSubviews()
let duration: TimeInterval = 3.0
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
// initial transform
self.alpha = 0
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// initial spin for duration of animaton
UIView.animate(withDuration: duration,
delay: 0.0,
options: [.curveLinear],
animations: {
self.transform = rotate;
},
completion: nil)
// scaling and fading
UIView.animate(withDuration: duration/2.0, animations: {
self.transform = self.transform.scaledBy(x: 0.8, y: 0.8)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration: duration/2.0, animations: {
self.transform = self.transform.scaledBy(x: 0.1, y: 0.1)
self.alpha = 0
})
}
}
根据您修改后的要求,我正在使用块动画扩展您已经看到的内容。正如一些人所说,无论如何,关键帧动画可能会更好,这是我的想法。
创建一个通过变换视图来旋转整个时间的动画。 创建另一个基于当前变换(正在旋转)进行缩放和淡入淡出的动画。在此过程中,我刚刚创建了一些变量以允许您自定义(和重复)动画的某些部分。为了清楚起见,我打破了一些东西,并且知道我可以重构以写得更简洁。
这是代码
import UIKit
class OrangeView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
let duration: TimeInterval = 9.0
self.transform = CGAffineTransform.identity
// initial transform
self.alpha = 1
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// start rotation
rotate(duration: duration)
// scaling and fading
scaleUpAndDown(desiredRepetitions: 3, initalDuration: duration)
}
func rotate(duration: TimeInterval) {
UIView.animate(withDuration: duration/2.0,
delay: 0.0,
options: [.curveLinear], animations: {
let angle = Double.pi
self.transform = self.transform.rotated(by: CGFloat(angle))
}, completion: {[weak self] finished in
guard let strongSelf = self else {
return
}
if finished &&
strongSelf.transform != CGAffineTransform.identity {
strongSelf.rotate(duration: duration)
} else {
// rotation ending
}
})
}
func scaleUpAndDown(timesRepeated: Int = 0, desiredRepetitions: Int, initalDuration: TimeInterval) {
guard timesRepeated < desiredRepetitions,
desiredRepetitions > 0, initalDuration > 0 else {
self.transform = CGAffineTransform.identity
return
}
let repeatedCount = timesRepeated + 1
let scalingDuration = initalDuration/2.0/Double(desiredRepetitions)
UIView.animate(withDuration: scalingDuration,
delay: 0.0,
animations: {
let desiredOriginalScale: CGFloat = 0.8
let scaleX = abs(CGAffineTransform.identity.a / self.transform.a) * desiredOriginalScale
let scaleY = abs(CGAffineTransform.identity.d / self.transform.d) * desiredOriginalScale
self.transform = self.transform.scaledBy(x: scaleX, y: scaleY)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration:scalingDuration,
delay: 0.0,
animations: {
let desiredOriginalScale: CGFloat = 0.1
let scaleX = abs(CGAffineTransform.identity.a / self.transform.a) * desiredOriginalScale
let scaleY = abs(CGAffineTransform.identity.d / self.transform.d) * desiredOriginalScale
self.transform = self.transform.scaledBy(x: scaleX, y: scaleY)
self.alpha = 0
}) { finshed in
self.scaleUpAndDown(timesRepeated: repeatedCount, desiredRepetitions: desiredRepetitions, initalDuration: initalDuration);
}
}
}
}
终于来一张gif动图