1

我从未专门在 iOS 上使用过动画,希望能指出正确的方向。到目前为止,我已经以类似于下面的方式为一堆药丸状对象设置了动画,但是我还没有根据形状的 y 位置实现正确的遮罩。

正弦波

药丸形状只是 UIView。我正在寻找一种方法来根据他们的定位改变他们的背景;背景本身不动,只是药丸。

编辑:

根据下面 Rob 的回答,我现在将动画与设备的运动联系起来,如下所示:

- (void)setAnimationToDeviceMotion {
    motionManager = [[CMMotionManager alloc] init];
    motionManager.deviceMotionUpdateInterval = 0.1f;
    NSOperationQueue *motionQueue = [[NSOperationQueue alloc] init];

    [motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:motionQueue withHandler:^(CMDeviceMotion *motion, NSError *error) {
        if (!error) {
            double pitch = motion.attitude.pitch;
            NSLog(@"%f", pitch);
            [self addMaskToView:self.imageView withAdjustment:pitch];
        }
    }];
}
4

2 回答 2

3

假设这是八个药丸形状,下面会显示一个图像,你

  • UIBezierPath为八个药丸形状创建一个
  • 创建一个CAShapeLayer使用它UIBezierPath(或更准确地说,它的CGPath)的层
  • 应用这个作为CAShapeLayer你的masklayerUIImageView

如果您想随着时间的推移对其进行动画处理,只需替换mask(例如响应加速度计事件、aCADisplayLinkNSTimer或 a UIPanGesture),或者只需pathCAShapeLayer您作为蒙版应用到UIImageView' 层的 更新。

因此,您可能有类似的东西:

- (void)addMaskToView:(UIView *)view withAdjustment:(CGFloat)adjustment
{
    CAShapeLayer *mask = [CAShapeLayer layer];
    mask.path = [[self pillsPathWithAdjustment:adjustment forView:view] CGPath];

    self.imageView.layer.mask = mask;
}

- (UIBezierPath *)pillsPathWithAdjustment:(CGFloat)adjustment forView:(UIView *)view
{
    UIBezierPath *path = [UIBezierPath bezierPath];

    for (NSInteger i = 0; i < kNumberOfPills; i++)
        [self addPillPathNumber:i forView:view toPath:path adjustment:adjustment];

    return path;
}

- (void)addPillPathNumber:(NSInteger)index forView:(UIView *)view toPath:(UIBezierPath *)path adjustment:(CGFloat)adjustment
{
    CGFloat const pillSpacing = 5.0f;
    CGFloat const pillWidth = view.bounds.size.width / kNumberOfPills - pillSpacing;
    CGFloat const pillHeight =  view.bounds.size.height * 0.4;
    CGFloat const cornerRounding = 10.0f;

    CGPoint point = CGPointMake(index * (pillWidth + pillSpacing) + pillSpacing / 2.0, sinf((float) index * M_PI / kNumberOfPills + adjustment * M_PI * 2.0) * 100.0);

    // top

    point.x += cornerRounding;
    [path moveToPoint:point];
    point.x += pillWidth - cornerRounding * 2.0;
    [path addLineToPoint:point];

    // top right corner

    [path addArcWithCenter:CGPointMake(point.x, point.y + cornerRounding) radius:cornerRounding startAngle:3 * M_PI_2 endAngle:2.0 * M_PI clockwise:YES];
    point.x += cornerRounding;
    point.y += cornerRounding;

    // right

    point.y += pillHeight - cornerRounding * 2.0;
    [path addLineToPoint:point];

    // lower right corner

    [path addArcWithCenter:CGPointMake(point.x - cornerRounding, point.y) radius:cornerRounding startAngle:0 endAngle:M_PI_2 clockwise:YES];

    // bottom

    point.y += cornerRounding;
    point.x -= cornerRounding;
    point.x -= pillWidth - cornerRounding * 2.0;
    [path addLineToPoint:point];

    // lower left corner

    [path addArcWithCenter:CGPointMake(point.x, point.y - cornerRounding) radius:cornerRounding startAngle:M_PI_2 endAngle:M_PI clockwise:YES];

    // left

    point.y -= cornerRounding;
    point.x -= cornerRounding;
    point.y -= pillHeight - cornerRounding * 2.0;
    [path addLineToPoint:point];

    // upper left corner

    [path addArcWithCenter:CGPointMake(point.x + cornerRounding, point.y) radius:cornerRounding startAngle:M_PI endAngle:3.0 * M_PI_2 clockwise:YES];

    [path closePath];
}

举例来说,这就是我使用以下动画的方式CADisplayLink

- (void)startDisplayLink
{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    self.startTime = CACurrentMediaTime();
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink
{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
    CGFloat seconds;
    CGFloat fractionsOfSecond = modff(CACurrentMediaTime() - self.startTime, &seconds);

    [self addMaskToView:self.imageView withAdjustment:fractionsOfSecond];
}
于 2013-08-10T12:17:28.687 回答
0

要进行遮罩,您需要使用视图的图层。与其上下移动视图本身,不如创建占据父级整个高度的视图,然后CALayer在药丸形状中创建一个。将药丸层设置为视图层的蒙版,并上下移动。

像这样的东西:

UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"redAndBlueBackground"]];

CALayer *pillLayer = [[CALayer alloc] initWithFrame:CGRectMake(0, 0, myImageView.bounds.size.width, myImageView.bounds.size.height / 2];
pillLayer.cornerRadius = 8;
myImageView.layer.maskLayer = pillLayer;

// move the pill layer to height y:
pillLayer.center = CGPointMake(myImageView.bounds.size.width / 2, 
                               (myImageView.bounds.size.height / 2) + y);
于 2013-08-10T07:32:53.600 回答