简体   繁体   中英

Core Animation: Setting animated property correctly

I am currently trying to build a bar graph view using Core Animation and layers. To make it cooler I tried to let each beam pop up a bit, one after another. For convenience I flipped the coordinate system of the view vertically.

Here's the code:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.transform = CGAffineTransformMakeScale(1, -1);
        self.values = @[@12.5f, @4.25f, @23.0f, @3.0f, @17.9f, @7.0f, @15.1f];
    }
    return self;
}

- (void)didMoveToSuperview
{
    self.backgroundColor = [UIColor whiteColor];
    self.beamContainer = [CALayer layer];
    CGRect frame = CGRectInset(self.bounds, 20, 20);
    self.beamContainer.frame = frame;
    self.beamContainer.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1].CGColor;
    float maxValue = [[self.values valueForKeyPath:@"@max.floatValue"] floatValue];
    for (int i = 0; i < self.values.count; i++) {
        CALayer *beam = [CALayer layer];
        CGFloat beamHeight = ([self.values[i] floatValue] * frame.size.height) / maxValue;

        beam.backgroundColor = [UIColor colorWithRed:0.5 green:0.6 blue:1 alpha:1].CGColor;
        beam.anchorPoint = CGPointMake(0, 0);
        beam.position = CGPointMake(frame.size.width * ((float)i/(float)self.values.count), 0);
        CGRect endBounds = CGRectMake(0, 0, frame.size.width /(float)self.values.count, beamHeight);
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
        animation.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, frame.size.width /(float)self.values.count, 5)];
        animation.toValue = [NSValue valueWithCGRect:endBounds];
        animation.duration = .5;
        animation.beginTime = CACurrentMediaTime() + ((float)i * 0.1);
        [beam addAnimation:animation forKey:@"beamAnimation"];

        [self.beamContainer addSublayer:beam];
        beam.bounds = endBounds;
    }
    [self.layer addSublayer:self.beamContainer];
}

This works like a charm, the only problem is that if I don't write beam.bounds = endBounds; the beam will snap back to it's old bounds after the animation is finished . But when I do, It's going to use endBounds even before the animation has started and during the delay for each animation.

How can I animate the beam going from bounds A to B and sticking to B at the end ?

You could try something like the following:

// Save the original value
CGFloat originalY = layer.position.y;

// Change the model value (this is not animated yet)
layer.position = CGPointMake(layer.position.x, 300.0);

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];

// Now specify the fromValue for the animation because
// the current model value is already the correct toValue
animation.fromValue = @(originalY);
animation.duration = 1.0;

// Use the name of the animated property as key
// to override the implicit animation
[layer addAnimation:animation forKey:@"position"];

although it is not an exact match for the bar graph animations you are trying, you can likely get the pattern from the above example. You can read more about it here. It helped me with a similar issue I had the other day.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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