简体   繁体   中英

Animate the mask of a mask of a CALayer

Goal:
I am drawing a custom shape that has a gradient. I also want to animate the drawing of this shape by having it draw in from left to right.

Problem:
The code below works on an iPad simulator, but it doesn't work on my iPad 4 running iOS 7. Does anyone know how to make this work on the device? Is there a different way to achieve this same result?

Explanation of my Code:
My code works (only on simulator) using 3 CALayers.

  • gradientLayer holds my gradient.
  • shapeMaskLayer holds my custom shape.
  • animationMaskLayer animates it's path to simulate drawing from left to right

animationMaskLayer --masks--> shapeMaskLayer --masks--> gradientLayer

I then animate the frame of animationMaskLayer to animate the whole shape.

Code:

// Animation Mask Rects
CGPathRef leftStartingRectPath = CGPathCreateWithRect(CGRectMake(0, 0, 0, self.frame.size.height), 0);
CGPathRef fullViewRectPath = CGPathCreateWithRect(CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), 0);

// Animation Mask Layer
CAShapeLayer *animationMaskLayer = [CAShapeLayer layer];
animationMaskLayer.path = fullViewRectPath;
animationMaskLayer.fillColor = UIColor.blackColor.CGColor;

// Shape Mask Layer
CAShapeLayer *shapeMaskLayer = [CAShapeLayer layer];
shapeMaskLayer.path = CGPathCreateWithEllipseInRect(self.bounds, 0);
shapeMaskLayer.fillColor = [UIColor blueColor].CGColor;
shapeMaskLayer.mask = animationMaskLayer;

// Gradient Layer
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.bounds;
gradientLayer.colors = self.colors;
gradientLayer.mask = shapeMaskLayer;
mountainLayer.anchorPoint = pt(0, 0);
mountainLayer.position = pt(0, 0);
[self.layer addSublayer:gradientLayer];

// Left To Right Animation
CABasicAnimation *leftToRightAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
leftToRightAnimation.duration = 0.5;
leftToRightAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
leftToRightAnimation.fromValue = (__bridge id)leftStartingRectPath;
leftToRightAnimation.toValue = (__bridge id)fullViewRectPath;
leftToRightAnimation.fillMode = kCAFillModeForwards;
leftToRightAnimation.removedOnCompletion = NO;
[animationMaskLayer addAnimation:leftToRightAnimation forKey:@"animatePath"];

// Memory Management
CGPathRelease(leftStartingRectPath);
CGPathRelease(fullViewRectPath);

Animating the mask of a mask? I'm surprised that even works in the simulator.

Have you tried nesting two layers, with the parent layer with masksToBounds on? You can then set an independent mask on both layers, and the outer layer will effectively mask your inner layer with its own mask (due to masksToBounds ). It probably doesn't matter which layer gets which mask (because you want the intersection of both masks).

With the code you listed in your question, you would just need to add one line, and comment out one line to get the correct functionality:

self.layer.mask = animationMaskLayer;
//    shapeMaskLayer.mask = animationMaskLayer;

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