繁体   English   中英

如何在连续的repeatForever中链接Facebook pop动画?

[英]How to chain Facebook pop Animations in a continuous repeatForever?

SITUTATION:

我创造了一个脉动动画,它的工作原理。

使用repeatForever属性,我能够按照我的repeatForever使它连续。

但有一个问题仍然是我做了很多研究之后无法修复。


说明:

唯一的问题是我不知道如何添加一个动画,使Image在再次脉动之前恢复原始大小。

我面临的挑战在于,如果我在另一个之后声明它,它将不会被调用,因为它不会包含在repeatForever循环中。

因此,我现在拥有的动画并不平滑,因为一旦完成,图像会在重复之前立即恢复到原始大小。


怎么了:

1)图像脉动到当前大小的1.2到动画。

这不是很平滑的:

2)动画在1.2处完成,图像立即“扭曲”回到1.0

3)动画重复自己。 图像再次脉动到1.2。


问题:如何更改脉动动画以使我的图像在再次脉动之前以平滑的方式恢复到原始大小?


码:

import Foundation
import pop

class AnimationEngine {

    func pulsate(object: UIImageView) {
        let pulsateAnim = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
        pulsateAnim.velocity = NSValue(CGSize: CGSizeMake(0.1, 0.1))
        pulsateAnim.toValue = NSValue(CGSize: CGSizeMake(1.2, 1.2))
        pulsateAnim.springBounciness = 18
        pulsateAnim.dynamicsFriction = 20
        pulsateAnim.springSpeed = 1.0
        pulsateAnim.repeatForever = true
        // pulsateAnim.autoreverses = true
        object.layer.pop_addAnimation(pulsateAnim, forKey: "layerScaleSpringAnimation")
    }
}

我找到了解决方案。

解:

func pulsate(object: UIImageView) {
    let pulsateAnim = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
    let returnToSizeAnim = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)

    object.layer.pop_addAnimation(pulsateAnim, forKey: "layerScaleSpringAnimation")
    pulsateAnim.velocity = NSValue(CGSize: CGSizeMake(0.1, 0.1))
    pulsateAnim.toValue = NSValue(CGSize: CGSizeMake(1.2, 1.2))
    pulsateAnim.springBounciness = 30
    pulsateAnim.dynamicsFriction = 20
    pulsateAnim.springSpeed = 1.0
    pulsateAnim.completionBlock = {(animation, finished) in
        object.layer.pop_addAnimation(returnToSizeAnim, forKey: "layerScaleSpringAnimation")
    }
    returnToSizeAnim.toValue = NSValue(CGSize: CGSizeMake(1.0, 1.0))
    returnToSizeAnim.duration = 0.5
    returnToSizeAnim.completionBlock = {(animation, finished) in
        object.layer.pop_addAnimation(pulsateAnim, forKey: "layerScaleSpringAnimation")
    }
}

func pulsate2(object: UIImageView) {
    let pulsateAnim = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
    let returnToSizeAnim = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)

    object.layer.pop_addAnimation(pulsateAnim, forKey: "layerScaleSpringAnimation")
    pulsateAnim.velocity = NSValue(CGSize: CGSizeMake(0.1, 0.1))
    pulsateAnim.toValue = NSValue(CGSize: CGSizeMake(1.2, 1.2))
    pulsateAnim.springBounciness = 30
    pulsateAnim.dynamicsFriction = 20
    pulsateAnim.springSpeed = 1.0
    pulsateAnim.completionBlock = {(animation, finished) in
        object.layer.pop_addAnimation(returnToSizeAnim, forKey: "layerScaleSpringAnimation")
    }
    returnToSizeAnim.toValue = NSValue(CGSize: CGSizeMake(1.0, 1.0))
    returnToSizeAnim.duration = 0.5
    returnToSizeAnim.completionBlock = {(animation, finished) in
        object.layer.pop_addAnimation(pulsateAnim, forKey: "layerScaleSpringAnimation")
    }
}

注意:

我需要为每个想要使用它的对象声明一个脉动函数。 如果我不这样做,第二次调用该函数,它将无法正常工作,因为动画的实例已在运行。

我不知道Facebook pop ,所以我只谈到如何实现这个功能的分析和逻辑(脉冲效果)

正如我在评论中写的那样,你想做的事情似乎正是SpriteKit中多次发生的事情,你要制作一个特定的动画( SKAction ),必须建立一系列动作。

只是为了制作一个SpriteKit示例,这就是我做的特定脉冲效果:

let titleForward = runTitleForward()
let wait = SKAction.waitForDuration(5.0)
let titleBackward = runTitleBackward()
let titleAnim = SKAction.repeatActionForever((SKAction.sequence([titleForward, wait, titleBackward,wait ])))
title.runAction(titleAnim, withKey:"titleAnimation")

func runTitleForward()-> SKAction {
        let atlascTexturesArray = self.myManager.atlascTexturesDictionary["title-anim"]
        let texturesAction = SKAction.animateWithTextures(atlascTexturesArray!,timePerFrame: 0.09)        
        return texturesAction
    }

func runTitleBackward()-> SKAction {
    let texturesAction = runTitleForward()
    let texturesReverseAction = SKAction.reversedAction(texturesAction)
    return texturesReverseAction()
}

希望你能帮助UIKit做同样的事情。

更新 :(我不测试..)

func delayAnimation(duration:NSTimeInterval)-> CABasicAnimation {
   let animation : CABasicAnimation = CABasicAnimation(keyPath: "opacity");
   animation.delegate = self
   animation.fromValue = 1 
   animation.toValue = 1  // fake animation, just to obtain duration delay..
   animation.duration = duration
   return animation
}

func pulseElements () -> (POPSpringAnimation,POPSpringAnimation) {

        // zoom in
        let pulsateInAnim = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
        pulsateInAnim.velocity = NSValue(CGSize: CGSizeMake(0.1, 0.1))
        pulsateInAnim.toValue = NSValue(CGSize: CGSizeMake(1.2, 1.2))
        pulsateInAnim.springBounciness = 18
        pulsateInAnim.dynamicsFriction = 20
        pulsateInAnim.springSpeed = 1.0

        // zoom out
        let pulsateOutAnim = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
        ...

        return (pulsateInAnim,pulsateOutAnim)
}

func pulseAnimation() {
     let (pulsateInAnim,pulsateOutAnim) = pulseElements()
     let wait = delayAnimation(1.0)
     var pulseAnimationGroup: CAAnimationGroup = CAAnimationGroup()
     pulseAnimationGroup.animations = [pulsateInAnim, wait,  pulsateOutAnim, wait]
     pulseAnimationGroup.duration = 0.5
     pulseAnimationGroup.repeatCount = Float.infinity
     object.layer.addAnimation(pulseAnimationGroup, forKey: layerScaleSpringAnimation)
}

我是一个巨大的ReactiveCocoa书呆子所以我围绕POPAnimation构建了一个类,所以我可以以更实用的方式处理动画。

import Foundation
import ReactiveCocoa
import pop
import Result

/**
 `UIView` wrapper for performing reactive-based pop animations.
 */
public struct ReactivePOPView<View: UIView> {

    /// View object
    private weak var view: View?
    /// `SignalProducer` object when the wrapper is about to deallocate.
    private let willDealloc: SignalProducer<Void, NoError>

    /// Wrapper on the view property.
    private var animator: View? { return self.view }

    /**
     Create an animation wrapper with a view.

     - parameter view: `UIView` object.
     */
    public init(_ view: View) {
        self.view = view
        self.willDealloc = view
            .willDeallocSignalProducer()
        }
}

/**
 Binds a `Signal` that emits an animation object to a `ReactivePOPView`.

 - parameter view:   `ReactivePOPView` object.
 - parameter signal: `Signal` object.

 - returns: `Disposable` object.
 */
 public func <~ <T, Animation: POPAnimation>(view: ReactivePOPView<T>, signal: Signal<Animation, NoError>) -> Disposable {
    let disposable = CompositeDisposable()
    let viewDisposable = view.willDealloc.startWithCompleted {
        disposable.dispose()
    }
    disposable.addDisposable(viewDisposable)

    let signalDisposable = signal.observe(Observer(next: {
        view.animator?.pop_addAnimation($0, forKey: $0.name ?? "")

    }, completed: {
        disposable.dispose()
    }))
    disposable.addDisposable(signalDisposable)
    return disposable
}

/**
 Binds a `SignalProducer` that emits an animation object to a `ReactivePOPView`.

 - parameter view:     `ReactivePOPView` object.
 - parameter producer: `SignalProducer` object.

 - returns: `Disposable` object.
*/
public func <~ <T, Animation: POPAnimation>(view: ReactivePOPView<T>, producer: SignalProducer<Animation, NoError>) -> Disposable {
    var disposable: Disposable!
    producer.startWithSignal { signal, signalDisposable in
        view <~ signal
        disposable = signalDisposable

        view.willDealloc.startWithCompleted {
            signalDisposable.dispose()
        }
    }
    return disposable
}

/**
 Bind a reactive animation property to a `ReactivePOPView` property.

 - parameter destinationProperty: `ReactivePOPView` property.
 - parameter sourceProperty:      Animation property.

 - returns: `Disposable` object.
 */
public func <~ <T, P: PropertyType where P.Value == POPAnimation>(destinationProperty: ReactivePOPView<T>, sourceProperty: P) -> Disposable {
    return destinationProperty <~ sourceProperty.producer
}

通过这门课,你可以做以下事情:

ReactivePOPView<UIButton>(self.loginButton) <~ self.someSignal.signal
.flatMap(.Concat) { _ in SignalProducer<POPBasicAnimation, NoError> in
    let animation ...
    // construct animation here
    return SignalProducer(value: animation)
}
.repeat(0)

如果你想要的话,我也有一个约束包装类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM