Я пытаюсь создать довольно простую анимацию, используя объекты 6 CALayer
, каждая из которых маскируется по пути. Тем не менее, у меня возникают значительные запаздывания при попытке оживить их. Here is a video of the animation running. Я могу повысить производительность установки shouldRasterize
к YES
, однако это приводит к пикселизации текста, как вы можете видеть из этого изображения:Несколько масок 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 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++;
}
}
Любые предложения по улучшению производительности?
Единственное, что я вижу в вашем посте - это неподвижное изображение. Можете ли вы опубликовать ссылку на созданное видео? –
http://cl.ly/e28A – Hamish
Если вы готовы принять предварительный рендеринг (согласно комментариям в ответе Дункана), почему бы просто не создавать статические изображения в графическом приложении и не загружать их из каталога активов? Цвет фона может быть случайным. Этот метод не такой гибкий, но он, скорее всего, будет работать лучше. –