Several CALayer masks causing performance issues

I am trying to create a fairly simple animation using 6 CALayer objects, each of which is masked along the way. However, I have significant delays when trying to revive them. Here is a video with animation. I can improve performance by setting shouldRasterize to YES , however this results in pixelation of the text, as you can see from this image:

Horrible pixelation ..

I can fix the pixelation by setting rasterizationScale to the scale of the screen, however this will return the delay bursts that occurred without rasterization!

Here is my code:

 @interface splashLayer : CALayer @end @implementation splashLayer { UIColor* color; CALayer* l1, *l2, *l3, *l4, *l5, *l6; CAShapeLayer* m1, *m2, *m3, *m4, *m5, *m6; NSUInteger i; } -(instancetype) init { if (self = [super init]) { color = [lzyColors purpleColor]; i = 0; m1 = [CAShapeLayer layer]; m2 = [CAShapeLayer layer]; m3 = [CAShapeLayer layer]; m4 = [CAShapeLayer layer]; m5 = [CAShapeLayer layer]; m6 = [CAShapeLayer layer]; self.shouldRasterize = YES; self.rasterizationScale = screenScale(); // Slows down performance, but stops ugly pixelation. CGMutablePathRef p = CGPathCreateMutable(); CGFloat const meanScreenLength = (screenHeight()+screenWidth())*0.5; CGFloat const pythag = lzyMathsPythag(meanScreenLength, meanScreenLength); CGFloat const halfPythag = pythag*0.5; CGFloat const pythagHalfPythag = lzyMathsPythag(halfPythag, halfPythag); CGPoint const center = screenCenter(); CGPoint p1 = {center.x, center.y-pythagHalfPythag}; CGPoint p2 = {center.x+pythagHalfPythag, center.y}; CGPoint p3 = {center.x, center.y+pythagHalfPythag}; CGPoint p4 = {center.x-pythagHalfPythag, center.y}; CGPathMoveToPoint(p, nil, p1.x, p1.y); lzyCGPathAddLineToPath(p, p2); lzyCGPathAddLineToPath(p, p3); lzyCGPathAddLineToPath(p, p4); CGPathCloseSubpath(p); m1.path = p; m2.path = p; m3.path = p; m4.path = p; m5.path = p; m6.path = p; CGPathRelease(p); m1.position = (CGPoint){-pythag, -pythag}; m2.position = (CGPoint){-pythag, -pythag}; m3.position = (CGPoint){-pythag, -pythag}; m4.position = (CGPoint){pythag, pythag}; m5.position = (CGPoint){pythag, pythag}; m6.position = (CGPoint){pythag, pythag}; l1 = [CALayer layer]; l1.contents = (__bridge id _Nullable)(colorImage([color lightenByValue:0.6], screenSize()).CGImage); l1.frame = (CGRect){CGPointZero, screenSize()}; l1.mask = m1; l2 = [CALayer layer]; l2.contents = (__bridge id _Nullable)(textBG([color lightenByValue:0.3], screenSize()).CGImage); l2.frame = (CGRect){CGPointZero, screenSize()}; l2.mask = m2; l3 = [CALayer layer]; // l3.rasterizationScale = screenScale(); (Doesn't work) l3.contents = (__bridge id _Nullable)(textBG(color, screenSize()).CGImage); l3.frame = (CGRect){CGPointZero, screenSize()}; l3.mask = m3; UIColor* color2 = [lzyColors redColor]; l4 = [CALayer layer]; l4.contents = (__bridge id _Nullable)(colorImage([color2 lightenByValue:0.6], screenSize()).CGImage); l4.frame = (CGRect){CGPointZero, screenSize()}; l4.mask = m4; l5 = [CALayer layer]; l5.contents = (__bridge id _Nullable)(colorImage([color2 lightenByValue:0.3], screenSize()).CGImage); l5.frame = (CGRect){CGPointZero, screenSize()}; l5.mask = m5; l6 = [CALayer layer]; l6.contents = (__bridge id _Nullable)(colorImage(color2, screenSize()).CGImage); l6.frame = (CGRect){CGPointZero, screenSize()}; l6.mask = m6; [self addSublayer:l1]; [self addSublayer:l2]; [self addSublayer:l3]; [self addSublayer:l4]; [self addSublayer:l5]; [self addSublayer:l6]; CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:(CGPoint){-pythag, -pythag}]; anim.toValue = [NSValue valueWithCGPoint:CGPointZero]; anim.delegate = self; anim.beginTime = CACurrentMediaTime()+1; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; anim.removedOnCompletion = NO; anim.fillMode = kCAFillModeForwards; anim.duration = 1; [m1 addAnimation:anim forKey:@"0"]; anim.duration = 1.25; [m2 addAnimation:anim forKey:@"1"]; anim.duration = 1.5; [m3 addAnimation:anim forKey:@"2"]; anim.fromValue = [NSValue valueWithCGPoint:(CGPoint){pythag, pythag}]; anim.beginTime = CACurrentMediaTime()+2.5; anim.duration = 1; [m4 addAnimation:anim forKey:@"3"]; anim.duration = 1.25; [m5 addAnimation:anim forKey:@"4"]; anim.duration = 1.5; [m6 addAnimation:anim forKey:@"5"]; } return self; } @end 

I know the code is very rude, but I just simplified it for debugging.

The colorImage() and textBG() functions just do some Core Graphics rendering to create 6 images for 6 layers. This should not be the source of the problem, because the drawing is simple and the animation is delayed for a second before starting.

I tried setting the rasterizationScale value to the screen scale on the layers displaying the text, but this did not work.

I also tried to improve performance by deleting the two layers under the third layer as soon as he finished the animation, however he did not significantly improve the performance.

 -(void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { if (flag) { if (i == 2) { [l1 removeFromSuperlayer]; l1 = nil; m1 = nil; [l2 removeFromSuperlayer]; l2 = nil; m2 = nil; l3.mask = nil; m3 = nil; } i++; } } 

Any suggestions for improving performance?

0
source share
2 answers

Well, having tried countless methods to try and achieve this animation; I came to the conclusion that I'm probably best off doing a jump on openGL. This will allow me to create a more general solution to a problem that will be better with more complex animations.

0
source

I would suggest composing your layers and masks into static images and animations. It should be pretty fast.

+1
source

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


All Articles