基于iOS定位的图层蒙版

时间:2013-08-10 05:21:06

标签: ios animation core-animation quartz-graphics quartz-core

我从未专门在iOS上使用过动画,并且希望能指向正确的方向。到目前为止,我已经以类似于下面的方式动画了一堆药丸形状的物体,但是我还没有基于形状的y定位来实现正确的遮盖。

sine wave

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

修改

根据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];
        }
    }];
}

2 个答案:

答案 0 :(得分:3)

假设这是八个药丸形状,将揭示下面的单个图像,你

  • 为八个药丸形状创建UIBezierPath
  • 创建一个CAShapeLayer图层,使用UIBezierPath(或更准确地说,CGPath
  • 将此CAShapeLayer应用为mask的{​​{1}} layer

如果您想要随着时间的推移设置动画,只需替换UIImageView(例如,响应加速计事件,maskCADisplayLinkNSTimer) ,或者只是将您已应用为UIPanGesture的{​​{1}}更新为path图层。

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

CAShapeLayer

通过举例说明,这就是我使用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];
}

答案 1 :(得分: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);