SORU
1 Mart 2011, Salı


Nasıl özel hareket hızı oluşturma Temel Animasyon ile işlevi?

İOS oldukça güzel CGPath (QuadCurve) boyunca CALayer bir animasyon yapıyorum. Ama Apple tarafından provided birkaç (Easeİn/EaseOut vb.) daha ilginç hareket hızı işlevi kullanmak istiyorum. Örneğin, sıçrama ya da bir elastik fonksiyonu.

Bunları MediaTimingFunction ile yapmak mümkündür (bezier):

enter image description here

Ama yaratmak istiyorumzamanlama fonksiyonlarıbu daha karmaşıktır. Sorun zamanlama bu etkiler yaratacak kadar güçlü değil: kübik bezier gerektirecek gibi görünüyor ortam

enter image description here

Yukarıdaki oluşturmak için code Bu çok sinir bozucu kılan diğer çerçeveler, yeteri kadar basit. Eğrileri çıkış süresi (T-t eğrisi) ve zaman-pozisyon eğrileri değil giriş saati eşleme olduğunu unutmayın. Örneğin,(T) = t easeOutBouncedöndürür bir yenit. O zamanthareketi (animasyon etmeliyiz ne olursa olsun) çizmek için kullanılır.

Yani, 5* *karmaşık bir özel oluşturmak istiyorum ama bunu nasıl, ya da eğer mümkün mü onu bile bilmiyorum? Başka alternatif var mı?

DÜZENLEME:

İşte adımlar için somut bir örnek. Çok eğitici :)

  1. Noktasından bir hat boyunca bir nesneye animasyon eklemek istiyorumbiriçinb"hat boyunca hareketini yukarıda easeOutBounce eğrisini kullanarak." sıçrama etmek istiyorum ama ... Bu tam çizgi takip ederbiriçinbama ne mümkün olandan daha karmaşık bir şekilde hızlandırmak yavaşlayacaktır bezier tabanlı geçerli CAMediaTimingFunction kullanarak.

  2. Bu hat herhangi bir keyfi eğri hareketi yapmak CGPath ile belirtilen sağlar. Hala bu eğri boyunca hareket etmelidir, ama hızlandırmak ve çizgi örnekte olduğu gibi aynı şekilde yavaşlatmak gerekir.

Teoride böyle çalışması gerektiğini düşünüyorum

Sağlar hareketi kareyi bir animasyon eğri tanımlar(t) = p taşıyınneredettime [0..1]ppozisyon anında hesaplanırt. Bu yüzdenhareket(0)pozisyon eğrisi başlangıcında verirhareket(0.5)tam ortataşı(1)sonunda. Bir zamanlama fonksiyonuzaman(T) = tbu sağlamak içintdeğerler içinhareket ettirinbana istediğimi ver. Sıçrayan bir etki için, zamanlama işlevi aynı dönmelidirtdeğerler içinzaman(0.8)vezaman(0.8)(sadece bir örnek). Sadece zamanlama işlevi farklı bir etki elde etmek için değiştirin.

(Evet, mümkün ve ileri geri giden dört çizgi parçaları oluşturma katılarak line-sıçrayan, ama buna gerek yok. Sonuçta, bu sadece haritalar basit doğrusal bir fonksiyonzamanpozisyonlar için değerler.)

Burada mantıklı olduğumu umuyorum.

CEVAP
11 Mayıs 2011, ÇARŞAMBA


Bunu buldum:

Cocoa with Love - Parametric acceleration curves in Core Animation

Ama biraz daha basit ve daha okunabilir kullanarak blokları ile yapılabilir sanırım. Bu gibi bir şey görünüyor CAKeyframeAnimation bir kategori tanımlayabiliriz:

Parametrik CAKeyframeAnimation.h:

// this should be a function that takes a time value between 
//  0.0 and 1.0 (where 0.0 is the beginning of the animation
//  and 1.0 is the end) and returns a scale factor where 0.0
//  would produce the starting value and 1.0 would produce the
//  ending value
typedef double (^KeyframeParametricBlock)(double);

@interface CAKeyframeAnimation (Parametric)

  (id)animationWithKeyPath:(NSString *)path 
      function:(KeyframeParametricBlock)block
      fromValue:(double)fromValue
      toValue:(double)toValue;

Parametrik CAKeyframeAnimation.m:

@implementation CAKeyframeAnimation (Parametric)

  (id)animationWithKeyPath:(NSString *)path 
      function:(KeyframeParametricBlock)block
      fromValue:(double)fromValue
      toValue:(double)toValue {
  // get a keyframe animation to set up
  CAKeyframeAnimation *animation = 
    [CAKeyframeAnimation animationWithKeyPath:path];
  // break the time into steps
  //  (the more steps, the smoother the animation)
  NSUInteger steps = 100;
  NSMutableArray *values = [NSMutableArray arrayWithCapacity:steps];
  double time = 0.0;
  double timeStep = 1.0 / (double)(steps - 1);
  for(NSUInteger i = 0; i < steps; i  ) {
    double value = fromValue   (block(time) * (toValue - fromValue));
    [values addObject:[NSNumber numberWithDouble:value]];
    time  = timeStep;
  }
  // we want linear animation between keyframes, with equal time steps
  animation.calculationMode = kCAAnimationLinear;
  // set keyframes and we're done
  [animation setValues:values];
  return(animation);
}

@end

Şimdi kullanımı bu gibi bir şey olacaktır:

// define a parametric function
KeyframeParametricBlock function = ^double(double time) {
  return(1.0 - pow((1.0 - time), 2.0));
};

if (layer) {
  [CATransaction begin];
    [CATransaction 
      setValue:[NSNumber numberWithFloat:2.5]
      forKey:kCATransactionAnimationDuration];

    // make an animation
    CAAnimation *drop = [CAKeyframeAnimation 
      animationWithKeyPath:@"position.y"
      function:function fromValue:30.0 toValue:450.0];
    // use it
    [layer addAnimation:drop forKey:@"position"];

  [CATransaction commit];
}

İstediğin kadar basit olmayabilir biliyorum, ama bu bir başlangıç.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • dcigs

    dcigs

    9 EYLÜL 2006
  • modica89

    modica89

    24 HAZİRAN 2007
  • TheFlightsuit

    TheFlightsui

    22 HAZİRAN 2009