多个CALayer掩码导致性能问题 [英] Multiple CALayer masks causing performance issues

查看:101
本文介绍了多个CALayer掩码导致性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用6个 CALayer 对象创建一个相当简单的动画,每个对象都被一条路径遮盖。但是,在为动画设置动画时,我遇到了明显的延迟尖峰。



我可以通过设置 rasterizationScale 到屏幕比例,但是会带回没有光栅化发生的滞后尖峰!



这是我的代码:

  @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层]; m2 = [CAShapeLayer层]; m3 = [CAShapeLayer层]; m4 = [CAShapeLayer层]; m5 = [CAShapeLayer层]; m6 = [CAShapeLayer层];

self.shouldRasterize = YES;
self.rasterizationScale = screenScale(); //降低性能,但停止丑陋的像素化。

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层];
l1.contents =(__bridge id _Nullable)(colorImage([color lightenByValue:0.6],screenSize())。CGImage);
l1.frame =(CGRect){CGPointZero,screenSize()};
l1.mask = m1;

l2 = [CALayer层];
l2.contents =(__bridge id _Nullable)(textBG([color lightenByValue:0.3],screenSize())。CGImage);
l2.frame =(CGRect){CGPointZero,screenSize()};
l2.mask = m2;

l3 = [CALayer层];
// l3.rasterizationScale = screenScale(); (无效)
l3.contents =(__bridge id _Nullable)(textBG(color,screenSize())。CGImage);
l3.frame =(CGRect){CGPointZero,screenSize()};
l3.mask = m3;

UIColor * color2 = [lzyColors redColor];

l4 = [CALayer层];
l4.contents =(__bridge id _Nullable)(colorImage([color2 lightenByValue:0.6],screenSize())。CGImage);
l4.frame =(CGRect){CGPointZero,screenSize()};
l4.mask = m4;

l5 = [CALayer层];
l5.contents =(__bridge id _Nullable)(colorImage([color2 lightenByValue:0.3],screenSize())。CGImage);
l5.frame =(CGRect){CGPointZero,screenSize()};
l5.mask = m5;

l6 = [CALayer层];
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 =自我;
anim.beginTime = CACurrentMediaTime()+ 1;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

anim.removedOnCompletion =否;
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];


}
返回自我;
}

@end

我知道代码非常



colorImage()& textBG()函数仅执行一些Core Graphics渲染即可为6层生成6张图像。这不应该是问题的根源,因为绘图很简单,动画在开始之前会延迟一秒钟。



我尝试仅设置 rasterizationScale 到显示文本的图层上的屏幕比例,但这是行不通的。



我还尝试通过删除来提高性能一旦完成动画制作,第二层就位于第三层下面,但是它并没有显着提高性能。

 -(void )animationDidStop:(CAAnimation *)动画完成:(BOOL)flag {
if(flag){

if(i == 2){

[l1 removeFromSuperlayer];
l1 =零;
m1 =零;
[l2 removeFromSuperlayer];
l2 =零;
m2 =零;
l3.mask = nil;
m3 =零;
}

i ++;
}
}

关于如何改善效果的任何建议?

解决方案

好吧,尝试了无数种方法来尝试实现此动画之后;我得出的结论是,仅仅过渡到openGL可能会更好。这将使我能够为该问题创建一个更通用的解决方案,以便在使用更复杂的动画时效果更好。


I am trying to create a fairly simple animation using 6 CALayer objects, each masked by a path. However, I am running into significant lag spikes when trying to animate them. Here is a video of the animation running. I am able to boost performance by setting shouldRasterize to YES, however it results in pixelation of the text, as you can see from this image:

I can correct the pixelation by setting the rasterizationScale to the screen scale, however that brings back the lag spikes 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 crude, but I've just simplified it for debugging.

The colorImage() & textBG() functions just do some Core Graphics rendering to produce the 6 images for the 6 layers. This shouldn't be the source of the problem as drawing is simple and the animation is delayed by a second before starting.

I tried only setting the rasterizationScale to the screen scale on layers that display text, but this didn't work.

I have also tried to improve performance by removing the two layers underneath the third layer, once it has finished animating, however it hasn't improved performance significantly.

-(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 on how to improve the performance?

解决方案

Well, after trying countless methods to try and achieve this animation; I have arrived at the conclusion that I am probably better off just making the leap over to openGL. This will allow me to create a more general solution to the problem that'll fare better with more complex animations.

这篇关于多个CALayer掩码导致性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆