【问题标题】:Animate Change Height and Width at Different Times动画在不同时间更改高度和宽度
【发布时间】:2015-09-19 23:32:11
【问题描述】:

我有一个图像,我正在制作动画以使其看起来好像在“呼吸”。

目前,我使用以下代码使图像以一种体面的方式移动:(我正在为一个 UIView 设置动画,其中包含一些 UIImageView,它们都作为一个整体移动)

- (IBAction)animateButton:(id)sender {


    [UIView animateWithDuration:0.64
                          delay:0
                        options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
                     animations:^{
                         _testView.transform = CGAffineTransformMakeScale(1.08f, 1.02f);

                     } completion:nil];

}

但是,我似乎无法弄清楚如何以与 y 不同的速率在 x 中拉伸图像。这样做的目的是使图像看起来好像实际上是活的,而不会出现在清晰的重复运动中循环。

我尝试将UIView 的中心锚定到特定位置,然后通过让我们说 1.0 秒的动画在宽度上添加一些数字。 然后我尝试同时调用另一个动画,它只对高度执行相同的动画,添加不同的数量,持续大约 1.3 秒。但是我不能让这两个同时执行,因为一个会优先于另一个。

如果有人可以引导我以正确的方向以不同的速率为宽度和高度的重复拉伸设置动画,我将不胜感激。谢谢!

【问题讨论】:

    标签: ios objective-c animation transform cgaffinetransform


    【解决方案1】:

    考虑两个在时间上重叠的变化如下所示:

            |---- change x ---|
       |---- change y ----|
    

    如果两个区间是任意且重叠的,则可以用三个动画来表示:一个单独改变一个维度,一个同时改变两个维度,另一个单独改变一个维度。

    您可以看到有很多方法可以指定这一点,但让我们尝试一种简单的方法。为了避免复合比例的算术,让我们指定一个维度、一个像素变化和一个持续时间。比如……

    @[ @{@"dimension":@"width", @"delta":@10, @"duration":0.2},
       @{@"dimension":@"both", @"delta":@40, @"duration":0.8}, 
       @{@"dimension":@"width", @"delta":@10, @"duration":0.2} ]
    

    ... 意味着较长的宽度变化跨越较短的高度变化。你可以看到这是一个非常完整的语言来完成你想要的。

    我们需要一个动画方法来连续执行更改。一种简单的方法是将操作数组视为待办事项列表。递归算法说:要做一列事情,先做第一个,然后再做剩下的……

    - (void)animateView:(UIView *)view actions:(NSArray *)actions completion:(void (^)(BOOL))completion {
        if (actions.count == 0) return completion(YES);
        NSDictionary *action = actions[0];
        NSArray *remainingActions = [actions subarrayWithRange:NSMakeRange(1, actions.count-1)];
        [self animateView:view action:action completion:^(BOOL finished) {
            [self animateView:view actions:remainingActions completion:completion];
        }];
    }
    

    对于动画,您可能希望对中间动画使用线性时序曲线,但我可以看到您变得更加精细,并在列表的开头和结尾更改时序曲线。

    - (void)animateView:(UIView *)view action:(NSDictionary *)action completion:(void (^)(BOOL))completion {
        NSString *dimension = action[@"dimension"];
        CGFloat delta = [action[@"delta"] floatValue];
        NSTimeInterval duration = [action[@"duration"] floatValue];
    
        CGRect frame = view.frame;
    
        if ([dimension isEqualToString:@"width"]) {
            frame = CGRectInset(frame, -delta, 0);
        } else if ([dimension isEqualToString:@"height"]) {
            frame = CGRectInset(frame, 0, -delta);
        } else {
            frame = CGRectInset(frame, -delta, -delta);
        }
        [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
            view.frame = frame;
        } completion:completion];
    }
    

    如果字典数组太笨拙而无法指定(而且它相当笼统),您可以在顶部添加一些便利方法,为调用者提供一些更简单的方案并构建更通用的表示数组。

    【讨论】:

    • 感谢您的深入回应——我一直在干预这样的理论,但在准确执行它时遇到了一些麻烦。希望这最终会引导我朝着正确的方向前进。
    • 如果是我,我会把它放在它自己的小项目中(或者至少它是你当前项目中自己的视图控制器),然后用组合来玩弄。一开始我会使用很长的持续时间,这样我就可以看到发生了什么。
    猜你喜欢
    • 2021-02-01
    • 2012-05-16
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    相关资源
    最近更新 更多