我正在创建一个动画,我想在应用程序在线检索某些数据时使用该动画。我的想法是,我连续有一些点,它们将缩小,原始尺寸然后恢复到原始尺寸,所有这些都在每次缩放之间有一个小延迟。重复动画并使用自动反转模式。
为此,我使用核心图形方法创建一些点,将它们添加到视图中并使用CGAffineTransformMakeTranslation
转换定位它们。然后我使用一个循环来逐个动画它们,并使用CGAffineTransformScale
转换进行缩放。
问题:我没有得到预期的动画(至少是我所期待的)。当缩放点时,它们也会移回原始位置。
有人可以告诉我为什么在UIView
动画中有翻译转换,我只是指定缩放?
以下是代码:
private var dots = [UIImage]()
public init(numberOfDots: Int, hexaColor: Int, dotDiameter: CGFloat = 30, animationDuration: NSTimeInterval = 1) {
self.dotDiameter = dotDiameter
self.animationDuration = animationDuration
for _ in 0 ..< numberOfDots {
dots.append(GraphicHelper.drawDisk(hexaColor, rectForDisk: CGRect(x: 0, y: 0, width: dotDiameter, height: dotDiameter), withStroke: false))
}
let spaceBetweenDisks: CGFloat = dotDiameter / 3
let viewWidth: CGFloat = CGFloat(numberOfDots) * dotDiameter + CGFloat(numberOfDots - 1) * spaceBetweenDisks
super.init(frame: CGRectMake(0, 0, viewWidth, dotDiameter))
setup()
}
private func setup() {
for (i, dot) in dots.enumerate() {
let dotImageView = UIImageView(image: dot)
addSubview(dotImageView)
let spaceBetweenDisks: CGFloat = dotDiameter / 3
let xOffset = CGFloat(i) * (dotDiameter + spaceBetweenDisks)
dotImageView.transform = CGAffineTransformMakeTranslation(xOffset, 0)
}
}
public func startAnimation() {
for i in 0 ..< self.dots.count {
let dotImageView: UIImageView = self.subviews[i] as! UIImageView
let transformBeforeAnimation = dotImageView.transform
let delay: NSTimeInterval = NSTimeInterval(i)/NSTimeInterval(self.dots.count) * animationDuration
UIView.animateWithDuration(animationDuration, delay: delay, options: [UIViewAnimationOptions.Repeat, UIViewAnimationOptions.Autoreverse], animations: {
dotImageView.transform = CGAffineTransformScale(dotImageView.transform, 0.05, 0.05)
}, completion: { finished in
dotImageView.transform = CGAffineTransformIdentity
dotImageView.transform = transformBeforeAnimation
})
}
}
编辑:
我找到了修复但我不明白为什么要修复它。所以,如果有人可以解释。
我添加了这两行:
dotImageView.transform = CGAffineTransformIdentity
dotImageView.transform = transformBeforeAnimation
在startAnimation
中的这一行之前:
dotImageView.transform = CGAffineTransformScale(dotImageView.transform, 0.05, 0.05)
答案 0 :(得分:2)
结合翻译和缩放变换令人困惑,很难做到正确。
我必须花太多时间用方格纸和深思熟虑才能搞清楚,我现在太累了。
不要那样做。通过移动中心坐标放置点图像视图,并将变换保留为标识。然后,当你缩放它们时,它们应该按照你想要的方式缩放。
请注意,如果您希望它们同时移动和缩放,您可以更改视图的center属性,并在同一animateWithDuration调用中进行变换缩放,并且它可以正常工作。 (顺便更改框架不是这样。如果更改了转换,那么框架属性就不再正常工作了.Apple的文档说明了使用非标识转换读取/写入视图的frame属性的结果是“未定义”。)
答案 1 :(得分:1)
你确定它会回到原来的位置,而不是根据原来的中心点进行缩放吗?尝试更改应用变换的顺序:
public func startAnimation() {
for i in 0 ..< self.dots.count {
let dotImageView: UIImageView = self.subviews[i] as! UIImageView
let transformBeforeAnimation = dotImageView.transform
let delay: NSTimeInterval = NSTimeInterval(i)/NSTimeInterval(self.dots.count) * animationDuration
UIView.animateWithDuration(animationDuration, delay: delay, options: [UIViewAnimationOptions.Repeat, UIViewAnimationOptions.Autoreverse], animations: {
// make scale transform separately and concat the two
let scaleTransform = CGAffineTransformMakeScale(0.05, 0.05)
dotImageView.transform = CGAffineTransformConcat(transformBeforeAnimation, scaleTransform)
}, completion: { finished in
dotImageView.transform = CGAffineTransformIdentity
dotImageView.transform = transformBeforeAnimation
})
}
}
来自apple docs:
请注意,矩阵运算不是可交换的 - 连接矩阵的顺序很重要。也就是说,矩阵t1乘以矩阵t2的结果不一定等于矩阵t2乘以矩阵t1的结果。
因此,请记住,分配转换会创建一个新的仿射变换矩阵,并且连接将使用新的矩阵修改现有矩阵 - 您应用这些矩阵的顺序可能会产生不同的结果。
为了完成这项工作,我还在dotImageView
上更新了您的翻译价值。如果在比例尺之前应用翻译,则需要requiredTranslation / scale
..所以在viewDidLoad
:
dotImageViewtransform = CGAffineTransformMakeTranslation(1000, 0)
然后是动画:
// make scale transform separately and concat the two
let scaleTransform = CGAffineTransformMakeScale(0.05, 0.05)
self.card.transform = CGAffineTransformConcat(transformBeforeAnimation, scaleTransform)