Как я могу связать Core Animations для разных слоев один за другим? - PullRequest
10 голосов
/ 03 февраля 2012

У меня есть scrollView с включенной подкачкой и число N страниц, которые являются UIViews как подпредставления scrollView.

Я пытаюсь сделать следующее:

Пользователь прокручивает дономер страницы n.В этот момент 7 CALayers, которые ранее были добавлены на страницу номер n (то есть на страницу [[scrollView subviews] objectAtIndex: n-1] .layer subLayers]), появляются один за другим.

Но я не могу понять, как сделать CALayers fadeIn последовательно. Итак, я попробовал следующие 3 подхода из метода делегата моего контроллера: (Предположим, у меня есть массив для слоев, и что их непрозрачность была установлена ​​на 0 присоздание)

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
  int pageNumber = floor(self.scrollView.contentOffset.x / self.scrollView.frame.size.width);
  if(pageNumber == (n-1))
  {
    int timeOffset = 0;

    [CATransaction begin];
    for(CALayer *layer in layerArray)
    {
      CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"];
      a.duration = 6;
      a.beginTime = timeOffset++;
      a.fromValue = [NSNumber numberWithFloat:0.];
      a.toValue = [NSNumber numberWithFloat:1.];

      [layer addAnimation:a forKey:nil];
    }
    [CATransaction commit];
  }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
  int pageNumber = floor(self.scrollView.contentOffset.x / self.scrollView.frame.size.width);
  if(pageNumber == (n-1))
  {
    int timeOffset = 0;

    [CATransaction begin];
    for(CALayer *layer in layerArray)
    {
      CABasicAnimation *a = [CABasicAnimation animation];
      a.duration = 6;
      a.beginTime = timeOffset++;
      [layer addAnimation:a forKey:@"opacity"];
      [layer setOpacity:1];
    }
    [CATransaction commit];
  }
}


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
  int pageNumber = floor(self.scrollView.contentOffset.x / self.scrollView.frame.size.width);
  if(pageNumber == (n-1))
  {
    int timeOffset = 0;


    for(CALayer *layer in layerArray)
    {
      [CATransaction begin];
      CABasicAnimation *a = [CABasicAnimation animation];
      a.duration = 6;
      a.beginTime = timeOffset++;
      [layer addAnimation:a forKey:@"opacity"];
      [layer setOpacity:1];
    }

    for(CALayer *layer in layerArray)
      [CATransaction commit];
  }
}

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

Есть идеи?

Ответы [ 3 ]

18 голосов
/ 10 февраля 2012

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

Например, что-то похожее на этот код приведет к тому, что n слоев (предполагается, что они хранятся в каком-либо массиве) будут последовательно исчезать один за другим, каждый из которых занимает 0,8 сек .:

  CGFloat timeOffset = 0;
  [CATransaction begin];
  for(CALayer *layer in layers)
  {
    CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"];
    a.fromValue = [NSNumber numberWithFloat:0.];
    a.toValue = [NSNumber numberWithFloat:1.];
    a.fillMode = kCAFillModeForwards;
    a.beginTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil] + timeOffset;
    a.duration = .8;
    a.removedOnCompletion = NO;
    [layer addAnimation:a forKey:nil];

    timeOffset += .8;
  }
  [CATransaction commit];

В приведенном выше случае система отсчета - это просто текущее время, когда выполняются вызовы.

5 голосов
/ 03 февраля 2012

Свойство beginTime для CAAnimation, похоже, работает, только если CAAnimation является частью CAAnimationGroup.Я думаю, вам также нужно установить свойство duration для CAAnimationGroup, достаточно большое, чтобы оно сохранялось до завершения финальной анимации.

https://stackoverflow.com/a/563486/77567

0 голосов
/ 30 июля 2017

В Swift 3 (слои - это массив CALayer или CAShapeLayer)

var timeOffset:Double = 0
for layer in layers {
    let a = CABasicAnimation(keyPath: "path"
    a.fromValue = layer.ovalPathSmall.cgPath
    a.toValue = layer.ovalPathLarge.cgPath
    a.fillMode = kCAFillModeForwards
    a.beginTime = CACurrentMediaTime() + timeOffset
    a.duration = 0.3
    a.isRemovedOnCompletion = false
    layer.add(a, forKey: nil)

    timeOffset += 0.3
}

И если вам интересно, что такое ovalPathSmall и ovalPathLarge:

ovalPathSmall = UIBezierPath(arcCenter: position, radius: smallRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
ovalPathLarge = UIBezierPath(arcCenter: position, radius: largeRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
...