4

Hello to you animation experts!

I've stumbled across Origami by Facebook that uses their Pop library for iOS.

Origami Examples

All the tutorials (on their site + everywhere else online) seem to focus on mastering the Quartz Composer side of it. I'm interested in how to get the exported code (Click on the Origami icon in QC and choose Export iOS code.) into my iOS app.

enter image description here

So I started by downloading the "2D Waggle" example: 2D Waggle Example

Here's what the exported code looks like:

#import "ViewController.h"
#import <POP/POP.h>
#import <POP/POPLayerExtras.h>

@interface ViewController ()
@property (nonatomic) CGFloat popAnimationProgress;
@property (nonatomic) CGFloat popAnimationProgress;
@end

@implementation ViewController

// popAnimation transition

- (void)togglePopAnimation:(BOOL)on {
  POPSpringAnimation *animation = [self pop_animationForKey:@"popAnimation"];

  if (!animation) {
    animation = [POPSpringAnimation animation];
    animation.springBounciness = 5;
    animation.springSpeed = 10;
    animation.property = [POPAnimatableProperty propertyWithName:@"popAnimationProgress" initializer:^(POPMutableAnimatableProperty *prop) {
      prop.readBlock = ^(ViewController *obj, CGFloat values[]) {
        values[0] = obj.popAnimationProgress;
      };
      prop.writeBlock = ^(ViewController *obj, const CGFloat values[]) {
        obj.popAnimationProgress = values[0];
      };
      prop.threshold = 0.001;
    }];

    [self pop_addAnimation:animation forKey:@"popAnimation"];
  }

  animation.toValue = on ? @(1.0) : @(0.0);
}

- (void)setPopAnimationProgress:(CGFloat)progress {
    _popAnimationProgress = progress;
    POPLayerSetTranslationX(self.layer.layer, POPPixelsToPoints(progress));
}

// popAnimation transition

- (void)togglePopAnimation:(BOOL)on {
  POPSpringAnimation *animation = [self pop_animationForKey:@"popAnimation"];

  if (!animation) {
    animation = [POPSpringAnimation animation];
    animation.springBounciness = 5;
    animation.springSpeed = 10;
    animation.property = [POPAnimatableProperty propertyWithName:@"popAnimationProgress" initializer:^(POPMutableAnimatableProperty *prop) {
      prop.readBlock = ^(ViewController *obj, CGFloat values[]) {
        values[0] = obj.popAnimationProgress;
      };
      prop.writeBlock = ^(ViewController *obj, const CGFloat values[]) {
        obj.popAnimationProgress = values[0];
      };
      prop.threshold = 0.001;
    }];

    [self pop_addAnimation:animation forKey:@"popAnimation"];
  }

  animation.toValue = on ? @(1.0) : @(0.0);
}

- (void)setPopAnimationProgress:(CGFloat)progress {
    _popAnimationProgress = progress;
    POPLayerSetTranslationY(self.layer.layer, POPPixelsToPoints(-progress));
}

// Utilities

static inline CGFloat POPPixelsToPoints(CGFloat pixels) {
    static CGFloat scale = -1;
    if (scale < 0) {
        scale = [UIScreen mainScreen].scale;
    }
    return pixels / scale;
}

And here is the code I've tried to use to interact with the generated stuff:

-(void)awakeFromNib
{
    UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];
    [self addGestureRecognizer:pan];
}


static float firstX=0,firstY=0;



-(void)move:(id)sender {
    [self bringSubviewToFront:[(UIPanGestureRecognizer*)sender view]];
    CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self];

    if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
        firstX = [[sender view] center].x;
        firstY = [[sender view] center].y;

        [self togglePopAnimationX:YES];
        [self togglePopAnimationY:YES];
    }
    else    if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
        [self togglePopAnimationX:NO];
        [self togglePopAnimationY:NO];
    }



    translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY+translatedPoint.y);

    //

    if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateChanged) {

        POPLayerSetTranslationX(self.layer, translatedPoint.x);
        POPLayerSetTranslationY(self.layer, translatedPoint.y);
        //[[sender view] setCenter:translatedPoint];
    }
}

Suffice to say, this DOES NOT work :(

So I suppose my question is how do I initiate the animation?

What I'm trying to do is simulate the "Swipe" input patch in QC Origami (see screenshot)

Showing the input stage of the animation in QC

If anyone has any ideas about what I'm doing wrong and how to call the animations correctly I would be most grateful.

Many thanks!

Chris Birch
  • 2,041
  • 2
  • 19
  • 22

1 Answers1

2

The key is to name each box/animation/setting in your screenshot to have its own objectName so you know which CA Layer it refers to. Then, when exporting the code, each popAnimation will have a specific name and be applied to a specific object.

Example: Instead of

@property (nonatomic) CGFloat popAnimationProgress;
self.layer.layer

You'll see

@property (nonatomic) CGFloat popAnimationProgress_Object1;
self.object2.layer
Eric
  • 4,063
  • 2
  • 27
  • 49