CABasicAnimation анимирует все, хотя должен анимировать только одну вещь

Я сделал кучу маленьких отдельных изображений, каждое с отдельным CALayer, и предполагается, что они появляются и исчезают асинхронно с разной скоростью. У каждого есть фоновый подслой и заливочный подслой. Таймер работает в фоновом режиме, чтобы анимировать каждый по отдельности в определенные моменты. Для текущего поведения программы вместо того, чтобы анимировать каждое отдельное, вместо этого анимируется весь экран вокруг него. Не могли бы вы помочь мне сделать так, чтобы он анимировал только одно изображение за раз?

РЕДАКТИРОВАТЬ: я должен был быть более ясным. Время не проблема. До того, как я переключился на CoreAnimation, эти изображения правильно анимировались в нужное время. Но главная проблема здесь в том, что когда я говорю анимировать одно изображение, анимируется весь экран, включая фоновую часть экрана за пределами всех изображений.

Следующий сегмент кода предназначен для создания многоуровневой структуры в коде UIView. Self относится к основному UIView. Возвращаемое значение используется для установки переменной-члена CALayer для класса, представляющего одно из этих маленьких изображений на экране.

- (CALayer *) createImageLayer:(CGPoint)orig Center:(CGPoint)pos {
    CALayer *parentLayer = [self layer];
    CALayer *childLayer1 = [CALayer layer];
    childLayer1.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer1.position = pos;
    CALayer *childLayer2 = [CALayer layer];
    childLayer2.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer2.position = pos;

    float components[4] = {1.0, 1.0, 1.0, 1.0};

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGColorRef whiteColor = CGColorCreate( colorSpace, components);

    childLayer1.backgroundColor = whiteColor;
    childLayer2.backgroundColor = whiteColor;

    UIImage *childImage = [UIImage imageNamed:@"back.png"];
    UIImage *childImage2 = [UIImage imageNamed:@"fill.png"];

    CGImageRef imageRef = [childImage CGImage];
    CGImageRef imageRef2 = [childImage2 CGImage];

    childLayer1.contents=(id)imageRef;
    childLayer2.contents=(id)imageRef2;

    [parentLayer addSublayer:childLayer1];
    [parentLayer addSublayer:childLayer2];

    CGColorSpaceRelease(colorSpace);
    CGColorRelease(whiteColor);

    return parentLayer;
}

Код, чтобы сказать ему анимировать. Объекту изображения предлагается добавить анимацию к своему члену слоя.

- (void) fadeAnimation:(ImageClass *)image {
    CABasicAnimation *theAnimation;

    theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
    theAnimation.duration=1.0; // fixed duration for now
    theAnimation.repeatCount=1;
    theAnimation.autoreverses=YES;
    theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
    theAnimation.toValue=[NSNumber numberWithFloat:0.0];
    [image.myLayer addAnimation:theAnimation forKey:@"animateOpacity"];
}

person William    schedule 22.06.2010    source источник


Ответы (1)


Во-первых, ваш код можно значительно сократить, что облегчит его чтение:

- (CALayer *) createImageLayer:(CGPoint)orig Center:(CGPoint)pos 
{    
    CALayer *childLayer1 = [CALayer layer];
    childLayer1.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer1.position = pos;

    CALayer *childLayer2 = [CALayer layer];
    childLayer2.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer2.position = pos;

    childLayer1.backgroundColor = [[UIColor whiteColor] CGColor];
    childLayer2.backgroundColor = [[UIColor whiteColor] CGColor];

    childLayer1.contents=(id)[[UIImage imageNamed:@"back.png"] CGImage];
    childLayer2.contents=(id)[[UIImage imageNamed:@"fill.png"] CGImage];

    [[self layer] addSublayer:childLayer1];
    [[self layer] addSublayer:childLayer2];

    return parentLayer;
}

Далее я бы предложил вместо создания таймера просто использовать -performSelector:withObject:afterDelay. Затем вы можете добавить все свои анимации сразу, просто изменив параметр afterDelay. Что-то вроде этого:

int i = 0;
for (i = 0; i < 10; ++i)
{
    [self performSelector:@selector(fadeAnimation:) 
               withObject:images[i] 
               afterDelay:(CGFloat)i];
}

Где images — это массив C ваших объектов ImageClass. Конечно, вам не придется использовать массив C. Вы можете использовать NSArray, но вам все равно понадобится счетчик для вашего параметра afterDelay. Это приведет к тому, что ваши анимации будут происходить каждую секунду. Я не уверен, что именно вы хотите, поэтому я просто показываю это в качестве примера.

Есть и другие способы сделать то, о чем вы просите, с помощью Core Animation. Вы можете посмотреть группировку анимации и beginTime, но я думаю, что упомянутый выше метод -peformSelector представляет собой путь с меньшим сопротивлением.

С наилучшими пожеланиями

person Matt Long    schedule 22.06.2010
comment
Спасибо за помощь. Основная проблема, с которой я столкнулся, заключается в том, что когда я думаю, что говорю каждому отдельному изображению выполнить анимацию затухания, например [self fadeAnimation:myImage], вместо этого оно выполняет анимацию для всего экрана, а не для изображения. Время для меня на самом деле не проблема, но я мог бы попробовать ваше предложение, поскольку оно кажется более подходящим для моих целей, чем таймер. - person William; 23.06.2010