2016-05-14 61 views
3

SITUTATION:如何在连续的repeatForever中链接Facebook流行动画?

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

使用repeatForever属性,我能够使其连续,因为我想。

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


说明:

唯一的问题是,我不知道如何添加一个动画,使图像回到它的原始尺寸再次搏动之前。

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

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


会发生什么:

1)图像脉动电流大小THX的1.2〜动画。

THIS IS NOT SMOOTH:

2)动画完成在1.2和图像即刻 “翘曲” 回1.0

3)动画重演。图像再次跳动到1.2。


问题:我怎样才能改变我的pulsatingAnimation让我的形象可以追溯到它的原始尺寸比较顺利地再次脉动过吗?


CODE:

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") 
    } 
} 
+1

@AlessandroOrnano伟大的thx :) Upvote – Coder1000

+0

'autoreverses'设置为'true'会发生什么?动画能够正常工作,但不会重复?是对的吗? – Sulthan

+0

@Sulthan不完全是,当autoreverses设置为true时,动画反向运行。这意味着它会随着我想变大而跳动,然后它会回到原来的大小(我不想这样,我想它会跳动,然后再顺利地返回到原来的大小,而不会再次脉动)。但动画无限重复,如想:) – Coder1000

回答

3

我找到了解决方案。

SOLUTION:

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") 
    } 
} 

N.B:

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

1

我不知道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

UPDATE:(我没有测试它..)

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) 
} 
+1

可悲的是,我没有能够重现这在Facebook流行,但它肯定帮助,谢谢! – Coder1000

+0

这很难,是否可以在块中使用POPSpringAnimation?完成按顺序制作两个动画。然后,有一个方法,如:animationWithanimation创建一个新的动画与序列repeatoverver它... –

+0

我想到了完成块,但我不知道如何创建一个新的动画序列,然后重复它:( – Coder1000

1

我是一个巨大的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) 

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

+0

这很好,但我可以一次传递2个动画,如:'return SignalProducer(value:animation1,animation2)'? – Coder1000

+0

确实没有办法只使用facebook Pop已经提供的功能来做什么? – Coder1000

+0

当然,您可以创建两个单独的动画信号并执行SignalProducer(values:[firstAnimationProducer,secondAnimationProducer])。flatten(.Merge)''这可以在动画触发时应用这两个动画,或者你可以执行'SignalProducer(values:[someTrigger.flatMap(.Latest){_ in animationSignal},otherTrigger.flatMap(.L atest){_ in secondAnimation}])。flatten(.Merge)' 可能有,我不知道。我不是pop的专家,这只是我使用动画和反应可可来简化的一种方式。 – barndog