2015-12-08 3 views
0

Я пытаюсь создать довольно простую анимацию, используя объекты 6 CALayer, каждая из которых маскируется по пути. Тем не менее, у меня возникают значительные запаздывания при попытке оживить их. Here is a video of the animation running. Я могу повысить производительность установки shouldRasterize к YES, однако это приводит к пикселизации текста, как вы можете видеть из этого изображения:Несколько масок CALayer, вызывающих проблемы с производительностью

Horrible pixelation..

я могу исправить пикселизация, установив 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 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 

Я знаю, что код очень сырой, но я только упрощен для отладки.

colorImage() & textBG() функции просто выполняют рендеринг основной графики, чтобы создать 6 изображений для 6 слоев. Это не должно быть источником проблемы, поскольку рисунок прост и анимация задерживается на секунду перед запуском.

Я попытался установить rasterizationScale на экранную шкалу на слоях, отображающих текст, но это не сработало.

Я также попытался улучшить производительность, удалив два слоя под третьим слоем, как только он закончил анимацию, однако он значительно не улучшил производительность.

-(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++; 
    } 
} 

Любые предложения по улучшению производительности?

+0

Единственное, что я вижу в вашем посте - это неподвижное изображение. Можете ли вы опубликовать ссылку на созданное видео? –

+0

http://cl.ly/e28A – Hamish

+0

Если вы готовы принять предварительный рендеринг (согласно комментариям в ответе Дункана), почему бы просто не создавать статические изображения в графическом приложении и не загружать их из каталога активов? Цвет фона может быть случайным. Этот метод не такой гибкий, но он, скорее всего, будет работать лучше. –

ответ

0

Ну, попробовав бесчисленные методы, чтобы попытаться достичь этой анимации; Я пришел к выводу, что мне, вероятно, лучше всего сделать прыжок на openGL. Это позволит мне создать более общее решение проблемы, которая будет лучше с более сложными анимациями.

1

Я бы предложил компоновку ваших слоев и масок в статические изображения и анимацию. Это должно быть очень быстро.

+0

Сначала я попытался это сделать, однако, поскольку он не пользуется преимуществами графического процессора, требуется много времени, чтобы предварительно визуализировать все изображения, необходимые для плавной анимации, занимать большие объемы памяти и не всегда воспроизводить плавно. – Hamish

+0

Вам необходимо предварительно визуализировать изображения при разрешении экрана.Вы должны сделать это один раз и только один раз, а затем сохранить изображения на диск и просто загрузить их и перейти. Изображение размером с экран можно быстро оживить. –

+0

Я был предварительным рендерингом при разрешении экрана, но я все же нашел, что анимация не всегда была гладкой и все еще занимала много времени для рендеринга. Я также хотел иметь случайный цвет фона (из 15 цветов или около того) для анимации; поэтому я бросился пытаться преподнести и отправился в ЦА. Я вернусь и даю предварительный перевод другому выстрелу и дам вам знать, как это происходит. – Hamish