IOS animation masks over UIImage

I am using Swift 1.2, and my goal is to animate the image mask on top of the static UIImage. I implemented a quick version of image masking that I originally found in Objective-C.

func maskImage(image: UIImage, mask: UIImage) -> UIImage! {

    let maskRef = mask.CGImage;

    let mask = CGImageMaskCreate(
        CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef), nil, false);

    let masked = CGImageCreateWithMask(image.CGImage, mask);
    let retImage = UIImage(CGImage: masked);
    return retImage;
}

It works great! However, its launch is my task.

Is there a way or iteratively apply a mask with a different horizontal offset, or is there a better way to completely approach this problem - perhaps with a CALayer implementation?

Thanks for your help!

EDIT: Based on what was posted as an answer, I added the following:

    let image = UIImage(named: "clouds");

    let imageView = UIImageView(image: image);
    let layer = CALayer();
    layer.contents = UIImage(named: "alpha-mask")?.CGImage;
    layer.bounds = CGRectMake(0, 0, image.size.width, image.size.height);

    // For other folks learning, this did not work
    //let animation = CABasicAnimation(keyPath: "bounds.origin.x");

    // This does work
    let animation = CABasicAnimation(keyPath: "position.x");

    animation.duration = 2;
    animation.delegate = self;
    animation.fillMode = kCAFillModeForwards;
    animation.repeatCount = 0;
    animation.fromValue = 0.0;
    animation.toValue = image.size.width;
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear);
    animation.removedOnCompletion = false;

    layer.addAnimation(animation, forKey: "transform");

    imageView.layer.mask = layer;

    self.addSubview(imageView);

I see the alpha mask correctly, but the animation does not work. Any ideas?

EDIT: I changed the code above and it works! I needed to do keyPath position.x. See above

+3
1

CALayer - , , CAShapeLayer.

CAShapeLayer .

CAAnimation, , layerStart / strokeEnd .

, , , - , . "undefined", .

, , :

http://wareto.com/using-core-animation-groups-to-create-animation-sequences-2

CAAnimationGroups, CAShapeLayer, .

GIF , , - " ", :

enter image description here

, Objective-C, Core Animation Swift. , , .

:

- (IBAction)doMaskAnimation:(id)sender;
{

  waretoLogoLarge.hidden = FALSE;//Show the image view

  //Create a shape layer that we will use as a mask for the waretoLogoLarge image view
  CAShapeLayer *maskLayer = [CAShapeLayer layer];

  CGFloat maskHeight = waretoLogoLarge.layer.bounds.size.height;
  CGFloat maskWidth = waretoLogoLarge.layer.bounds.size.width;

  CGPoint centerPoint;
  centerPoint = CGPointMake( maskWidth/2, maskHeight/2);

  //Make the radius of our arc large enough to reach into the corners of the image view.
  CGFloat radius = sqrtf(maskWidth * maskWidth + maskHeight * maskHeight)/2;

  //Don't fill the path, but stroke it in black.
  maskLayer.fillColor = [[UIColor clearColor] CGColor];
  maskLayer.strokeColor = [[UIColor blackColor] CGColor];

  maskLayer.lineWidth = radius; //Make the line thick enough to completely fill the circle we're drawing

  CGMutablePathRef arcPath = CGPathCreateMutable();

  //Move to the starting point of the arc so there is no initial line connecting to the arc
  CGPathMoveToPoint(arcPath, nil, centerPoint.x, centerPoint.y-radius/2);

  //Create an arc at 1/2 our circle radius, with a line thickess of the full circle radius
  CGPathAddArc(arcPath,
               nil,
               centerPoint.x,
               centerPoint.y,
               radius/2,
               3*M_PI/2,
               -M_PI/2,
               YES);

  maskLayer.path = arcPath;

  //Start with an empty mask path (draw 0% of the arc)
  maskLayer.strokeEnd = 0.0;

  CFRelease(arcPath);

  //Install the mask layer into out image view layer.
  waretoLogoLarge.layer.mask = maskLayer;

  //Set our mask layer frame to the parent layer bounds.
  waretoLogoLarge.layer.mask.frame = waretoLogoLarge.layer.bounds;

  //Create an animation that increases the stroke length to 1, then reverses it back to zero.
  CABasicAnimation *swipe = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  swipe.duration = 2;
  swipe.delegate = self;
  [swipe setValue: theBlock forKey: kAnimationCompletionBlock];

  swipe.timingFunction = [CAMediaTimingFunction 
    functionWithName:kCAMediaTimingFunctionLinear];
  swipe.fillMode = kCAFillModeForwards;
  swipe.removedOnCompletion = NO;
  swipe.autoreverses = YES;

  swipe.toValue = [NSNumber numberWithFloat: 1.0];

  [maskLayer addAnimation: swipe forKey: @"strokeEnd"];
}

, IS Swift , CAShapeLayer. , , , , .

:

http://wareto.com/swift-piecharts

+9

Source: https://habr.com/ru/post/1015882/


All Articles