在页面翻页动画中添加弹簧效果的CATransition

3

通过StackOverflow的帮助,我已经成功实现了在UIPageViewController中通过程序添加部分页面翻转的功能。这是对用户完成该页面/屏幕并可以继续的提示。

代码如下:

let animation = CATransition()
animation.duration = 0.3
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
animation.endProgress = 0.2
animation.type = "pageCurl"

myPageViewController.view.layer.add(animation, forKey: "MyTransition")

以下是它的样子(对于质量不佳的部分,我们表示歉意——mp4转gif效果不太好) enter image description here

现在我真正想做的是添加一些弹簧动画效果,这样看起来会更好一些。但我发现从谷歌上获取任何信息都非常困难(甚至可能不可能?)。

以下是我尝试过的方法:

// Can't see an animation type on here, maybe keyPath is used as the type?
let x = CASpringAnimation(keyPath: "pageCurl")

// No endProgress either, just trying some random values now
x.fromValue = 0
x.toValue = 1

// No idea - found on Google - can play with the settings later
x.damping = 5
x.duration = x.settlingDuration

// These look familiar from my working animation, so i'll set these!
x.fillMode = kCAFillModeForwards
x.isRemovedOnCompletion = false

myPageViewController.view.layer.add(x, forKey: "MyNewTransition")

...但实际上它什么都没做,甚至没有崩溃。我猜测这是因为你不能将 pageCurl 作为关键路径,iOS 不知道该如何处理它,所以它被忽略了。

以下是一个视频,大致展示了我想要的效果...

enter image description here

那么,有人知道是否可能使用一些弹簧来实现此 pageCurl 动画吗?


UIView有一个支持弹簧效果的animateWithDuration函数。 - u84six
我修改了我的评论,请看一下并告诉我你觉得是否可以。 - Adela Toderici
@Adela 看起来很不错。我稍后会测试一下!谢谢你的帮助。我需要再赚几个积分,但是一旦我再次获得50个积分,我就会添加另一个悬赏并把它给你 :) - TRG
1个回答

4

更新gif的编辑:

class ViewController: UIViewController {

var animated:Bool = false
var counter: Int = 0
var transition = CATransition()

override func viewDidLoad() {
    super.viewDidLoad()

    view.layer.backgroundColor = UIColor.white.cgColor
}

@IBAction func animate(_ sender: Any) {
    animated = false
    counter = 0
    animateCurlPage(start: 0.0, end: 0.35, duration: 0.4)
}

func animateCurlPage(start: Float, end: Float, duration: CFTimeInterval) {


    if (counter == 3) { return }

    UIView.animate(withDuration: duration, animations: {
        if (self.animated) { return }
        self.transition.type = "pageCurl"
        self.transition.subtype = kCATransitionFromBottom
        self.transition.duration = duration
        self.transition.startProgress = start
        self.transition.endProgress = end
        self.transition.delegate = self
        self.transition.fillMode = kCAFillModeForwards
        self.transition.isRemovedOnCompletion = false

        self.view.layer.add(self.transition, forKey: "transition1")
    })

    if animated {
        animateRepeatCurlPage()
    }
}

func animateRepeatCurlPage() {

    UIView.animate(withDuration: 0.15, animations: {
        self.transition.type = "pageCurl"
        self.transition.subtype = kCATransitionFromBottom
        self.transition.duration = 0.15
        self.transition.startProgress = 0.32
        self.transition.endProgress = 0.31
        self.transition.delegate = self
        self.transition.fillMode = kCAFillModeForwards
        self.transition.isRemovedOnCompletion = (self.counter == 2) ? true : false

        self.view.layer.add(self.transition, forKey: "transition2")
    })

    counter += 1
}
}

extension ViewController: CAAnimationDelegate {

func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    animateCurlPage(start: 0.35, end: 0.32, duration: 0.2)
    animated = true
}
}

这是代码的结果:

enter image description here

为了实现页面翻页动画和弹性动画,需要同时执行两个动画,因此需要使用动画组来处理,同时最重要的一点是对每个动画使用不同的关键字。在当前示例中,如果对两个动画使用相同的关键字:transition,则只会执行一个动画,通常是最后一个动画。
您可以稍微修改一下动画参数,我这里只是添加了一些任意值。
@IBAction func animate(_ sender: Any) {

    let animationGroup = CAAnimationGroup()
    animationGroup.duration = 5
    animationGroup.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
    animationGroup.animations = [animateCurlPage(), animateSpringTransition()]

    view.layer.add(animationGroup, forKey: "animation")
}

func animateCurlPage() -> CAAnimation {
    let transition = CATransition()
    transition.type = "pageCurl"
    transition.subtype = kCATransitionFromRight
    transition.duration = 1
    view.layer.add(transition, forKey: "transition")
    return transition
}

func animateSpringTransition() -> CAAnimation{
    let transitionX = CASpringAnimation(keyPath: "position.y")
    transitionX.duration = 0.5
    transitionX.fromValue = view.layer.position.y
    transitionX.toValue = view.layer.position.y - 60

    transitionX.damping = 5.0
    transitionX.initialVelocity = 1.0
    transitionX.stiffness = 20.0
    transitionX.beginTime = CACurrentMediaTime()
    view.layer.add(transitionX, forKey: "transitionX")
    return transitionX
}

这是结果:输入图像描述。这与IT技术有关。

谢谢您的回复,但并不是我正在寻找的。我已经在我的问题中添加了一些视频gif,以使其更清晰明了。 - TRG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接