我希望图层的行为如下:
相反,它的行为如下:
卡片翻转动画由CABasicAnimation
中应用的两个CAAnimationGroup
创建。发生不正确的旋转效果是因为CALayer
属性更改中的隐式动画首先运行,然后运行CABasicAnimation
中指定的动画。如何停止运行隐式动画,以便只运行指定的动画?
以下是相关代码:
class ViewController: UIViewController {
var simpleLayer = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
self.view.addGestureRecognizer(tap)
simpleLayer.frame = CGRect(origin: CGPoint(x: view.bounds.width / 2 - 50, y: view.bounds.height / 2 - 50), size: CGSize(width: 100, height: 100))
simpleLayer.backgroundColor = UIColor.blackColor().CGColor
view.layer.addSublayer(simpleLayer)
}
func handleTap() {
let xRotation = CABasicAnimation(keyPath: "transform.rotation.x")
xRotation.toValue = 0
xRotation.byValue = M_PI
let yRotation = CABasicAnimation(keyPath: "transform.rotation.y")
yRotation.toValue = 0
yRotation.byValue = M_PI
simpleLayer.setValue(M_PI, forKeyPath: "transform.rotation.y")
simpleLayer.setValue(M_PI, forKeyPath: "transform.rotation.x")
let group = CAAnimationGroup()
group.animations = [xRotation, yRotation]
group.duration = 0.6
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
simpleLayer.addAnimation(group, forKey: nil)
}
}
答案 0 :(得分:1)
@LucasTizma有正确的答案。
使用CATransaction.begin(); CATransaction.setDisableActions(true)
和CATransaction.commit()
围绕您的动画。这将disable the implicit animation并正确制作CAAnimationGroup
动画。
这是最终结果:
这是Swift 3中重要的代码片段:
CATransaction.begin()
CATransaction.setDisableActions(true)
let xRotation = CABasicAnimation(keyPath: "transform.rotation.x")
xRotation.toValue = 0
xRotation.byValue = M_PI
let yRotation = CABasicAnimation(keyPath: "transform.rotation.y")
yRotation.toValue = 0
yRotation.byValue = M_PI
simpleLayer.setValue(M_PI, forKeyPath: "transform.rotation.x")
simpleLayer.setValue(M_PI, forKeyPath: "transform.rotation.y")
let group = CAAnimationGroup()
group.animations = [xRotation, yRotation]
simpleLayer.add(group, forKey: nil)
CATransaction.commit()
这是使用iOS应用程序绘制动画的完整代码:
class ViewController: UIViewController {
var simpleLayer = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
self.view.addGestureRecognizer(tap)
let ratio: CGFloat = 1 / 5
let viewWidth = view.bounds.width
let viewHeight = view.bounds.height
let layerWidth = viewWidth * ratio
let layerHeight = viewHeight * ratio
let rect = CGRect(origin: CGPoint(x: viewWidth / 2 - layerWidth / 2,
y: viewHeight / 2 - layerHeight / 2),
size: CGSize(width: layerWidth, height: layerHeight))
let topRightPoint = CGPoint(x: rect.width, y: 0)
let bottomRightPoint = CGPoint(x: rect.width, y: rect.height)
let topLeftPoint = CGPoint(x: 0, y: 0)
let linePath = UIBezierPath()
linePath.move(to: topLeftPoint)
linePath.addLine(to: topRightPoint)
linePath.addLine(to: bottomRightPoint)
linePath.addLine(to: topLeftPoint)
let maskLayer = CAShapeLayer()
maskLayer.path = linePath.cgPath
simpleLayer.frame = rect
simpleLayer.backgroundColor = UIColor.black.cgColor
simpleLayer.mask = maskLayer
// Smooth antialiasing
// * Convert the layer to a simple bitmap that's stored in memory
// * Saves CPU cycles during complex animations
// * Rasterization is set to happen during the animation and is disabled afterwards
simpleLayer.rasterizationScale = UIScreen.main.scale
view.layer.addSublayer(simpleLayer)
}
func handleTap() {
CATransaction.begin()
CATransaction.setDisableActions(true)
CATransaction.setCompletionBlock({
self.simpleLayer.shouldRasterize = false
})
simpleLayer.shouldRasterize = true
let xRotation = CABasicAnimation(keyPath: "transform.rotation.x")
xRotation.toValue = 0
xRotation.byValue = M_PI
let yRotation = CABasicAnimation(keyPath: "transform.rotation.y")
yRotation.toValue = 0
yRotation.byValue = M_PI
simpleLayer.setValue(M_PI, forKeyPath: "transform.rotation.x")
simpleLayer.setValue(M_PI, forKeyPath: "transform.rotation.y")
let group = CAAnimationGroup()
group.animations = [xRotation, yRotation]
group.duration = 1.2
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
simpleLayer.add(group, forKey: nil)
CATransaction.commit()
}
}
答案 1 :(得分:-1)
您正在创建2个单独的动画并将其应用于动画组。当你这样做时,他们被应用为两个不连续的步骤。
看起来这不是你想要的。如果没有,则不要创建2个单独的动画,一个在transform.rotation.x上,另一个在transform.rotation.y上。相反,将两个更改连接到转换矩阵,并将更改的转换矩阵应用为单个动画。