问题
I'm trying to build transition for card flip & zoom. I've made its model in Origami - Movie (less that 1Mb)
As you can see there are 3 transforms applied at the same time: 1. moving center of the view to the centre of the screen 2. scaling 3. 3D rotte
We can divide animation on equal 2 phases:
Phase 1: Button scales, moves and rotates on the side (PI/2 radians). At the end of Phase 1 button disappears.
Phase 2: toView
(my modal view) rotates (from -PI/2 to 0 radians), scales up to the normal size and moves view's centre to the screen centre.
If we're excluding bouncing - it is pretty straightforward transforms.
But I've met several problems while building it:
1. I'm flipping just a button, not the whole view. There is a background behind this button. So, if I apply CATransform3DMakeRotation
half of the button disappears - it intersects with background in 3D space (Z axis). Is there a way to use 3DTransform here?
2. There are some artefacts on the screen. I don't have any idea where are they coming from.
You can check result movie (3.8Mb). I've slowed down animation for the second card in the movie.
Here is my code for this animation:
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView()
let fromViewBig = transitionContext.viewForKey(UITransitionContextFromViewKey)!
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
// Converting button to UIImageView and hiding actual button
let button = sourceViewController.view.viewWithTag(sourceViewController.buttonIndex)!
UIGraphicsBeginImageContextWithOptions(button.bounds.size, false, 0.0)
button.layer.renderInContext(UIGraphicsGetCurrentContext())
var img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
let fromView = UIImageView(frame: button.frame)
fromView.image = img
button.hidden = true
container.addSubview(toView)
container.addSubview(fromView)
let duration = self.transitionDuration(transitionContext)
// Add a perspective transform
var transform = CATransform3DIdentity
transform.m34 = -0.002
container.layer.sublayerTransform = transform
//calculating "median" frame size - size of the frame in 1/2 of animation
let medianX = (toView.frame.width + fromView.frame.width) / 2
let medianY = (toView.frame.height + fromView.frame.height) / 2
// at the midpoint of our animation final size of fromView should be equal to starting size of toView
// initial scale transfor fo toView (it will appear in second half of animation)
let initialToScaleTransform = CATransform3DMakeScale(medianX/toView.frame.width, medianY/toView.frame.height, 1.0)
// final scale of fromView
let finalFromScaleTransform = CATransform3DMakeScale(medianX/fromView.frame.width, medianY/fromView.frame.height, 1.0)
let finalToScaleTransform = CATransform3DMakeScale(1.0, 1.0, 1.0)
// our view is moving diring animation too
let startCenter = fromView.center
let endCenter = toView.center
let midCenter = CGPoint(x: (startCenter.x + endCenter.x)/2, y: (startCenter.y + endCenter.y)/2)
// flip the to VC halfway round - hiding it
toView.layer.transform = CATransform3DRotate(initialToScaleTransform, CGFloat(-M_PI_2), 0.0, 1.0, 0.0)
toView.center = midCenter
// animate
UIView.animateKeyframesWithDuration(duration, delay: 0, options: UIViewKeyframeAnimationOptions.allZeros, animations: { () -> Void in
UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.5, animations: { () -> Void in
fromView.layer.transform = CATransform3DRotate(finalFromScaleTransform, CGFloat(M_PI_2), 0.0, 1.0, 0.0)
fromView.center = midCenter
})
UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration: 0.5, animations: { () -> Void in
toView.layer.transform = CATransform3DRotate(finalToScaleTransform, 0.0, 0.0, 1.0, 0.0)
toView.center = endCenter
})
}) { (finished) -> Void in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}
来源:https://stackoverflow.com/questions/29017038/flip-and-zoom-3d-transition-problems-ios-7