Swift 4中CGAffineTransform实现顺时针旋转的问题求助
强制UIView动画执行顺时针旋转(避免自动选择最短路径)
我完全懂你的问题——UIView的动画默认会自动选择最短的旋转路径,所以当你想从-118°顺时针转到118°时,系统会发现逆时针转124°更短,就偷偷走了那条路,完全不符合你要的时钟指针转动效果。
下面给你两种可靠的解决方案,都能完美实现强制顺时针旋转:
方法一:使用累计变换(推荐,简单直观)
核心思路是:不要直接设置目标角度的transform,而是基于当前的transform累加一个顺时针旋转的角度,这样系统就会严格按照你指定的方向旋转,不会自作聪明选短路径。
代码示例:
// 1. 设置初始旋转角度(-118°) img_clock.transform = CGAffineTransform(rotationAngle: CGFloat(-118 * .pi / 180)) // 2. 计算需要顺时针旋转的总角度:从-118°到118°,顺时针需要转236° let totalClockwiseRotationDegree = 236.0 let totalClockwiseRotationRadian = CGFloat(totalClockwiseRotationDegree * .pi / 180) // 3. 执行动画:在初始transform基础上累加旋转角度 UIView.animate(withDuration: 15.0, delay: 0, options: .curveLinear, animations: { self.img_clock.transform = self.img_clock.transform.concatenating(CGAffineTransform(rotationAngle: totalClockwiseRotationRadian)) }, completion: { _ in // 可选:动画结束后,将transform重置为目标角度的归一化值(避免rotationAngle数值累积过大) self.img_clock.transform = CGAffineTransform(rotationAngle: CGFloat(118 * .pi / 180)) })
方法二:使用核心动画CAKeyframeAnimation
如果需要更精细的控制(比如中间加关键帧),可以用核心动画直接指定旋转的数值路径,绕过UIView动画的自动路径选择逻辑。
代码示例:
// 1. 设置初始旋转角度 img_clock.transform = CGAffineTransform(rotationAngle: CGFloat(-118 * .pi / 180)) // 2. 移除可能存在的旧动画 img_clock.layer.removeAllAnimations() // 3. 创建关键帧动画,指定旋转的起始和结束数值 let rotationAnimation = CAKeyframeAnimation(keyPath: "transform.rotation.z") rotationAnimation.duration = 15.0 rotationAnimation.timingFunction = CAMediaTimingFunction(name: .linear) // 这里直接用数值插值:从-118°的弧度,到-118°+236°的弧度(也就是118°) rotationAnimation.values = [ CGFloat(-118 * .pi / 180), CGFloat(-118 * .pi / 180 + 236 * .pi / 180) ] // 动画结束后保持最终状态 rotationAnimation.fillMode = .forwards rotationAnimation.isRemovedOnCompletion = false // 4. 添加动画到图层 img_clock.layer.add(rotationAnimation, forKey: "clockHandRotation")
为什么原来的代码不行?
你原来的代码直接设置目标transform为118 * .pi / 180,UIView动画会自动计算两个transform之间的最小旋转差:从-118°到118°,顺时针需要转236°,逆时针只需要转124°,系统会默认选更短的逆时针路径,这就是问题所在。
而上面两种方法,要么通过累计变换明确告诉系统“我要转236°”,要么通过核心动画的数值插值强制走指定路径,都能绕过这个自动选择逻辑。
内容的提问来源于stack exchange,提问作者Diego Garcia
相关产品推荐
相关产品推荐

