2010-01-04 16 views
10

मैं कई महत्वपूर्ण फ्रेम के साथ एक एनीमेशन बनाना चाहता हूं। मैं अपने लेयर (इस मामले में एक बटन) 1.5 तक स्केल करने के लिए 0.5 से नीचे तो 1.2 तक फिर नीचे 0.8 से 1.0 तक चाहता हूं।आप कैसे CAKeyframe एनीमेशन स्केल करते हैं?

मैं भी प्रत्येक कीफ्रेम के आसानी से और आसानी से करना चाहता हूं।

जैसा कि आप कल्पना कर सकते हैं, यह जगह पर एक स्प्रिंग/बाउंस प्रभाव पैदा करेगा।

मेरे ऐप के अन्य हिस्सों में मैं इस तरह से CAKeyframe एनीमेशन का उपयोग कर रहा हूं (नीचे कोड देखें)। यह एक समान वसंत एनीमेशन बनाता है लेकिन एक्स और वाई स्थिति के लिए।

क्या मैं नीचे दिए गए कोड को स्थिति के बजाय स्केल को प्रभावित करने के लिए अनुकूलित कर सकता हूं?

अग्रिम धन्यवाद!

- (CAAnimation*)monInAnimation { 
CGMutablePathRef path = CGPathCreateMutable(); 
CGPathMoveToPoint(path,NULL,113,320); 
CGPathAddLineToPoint(path, NULL, 113.5, 283); 
CGPathAddLineToPoint(path, NULL, 113.5, 179); 
CGPathAddLineToPoint(path, NULL, 113.5, 207); 
CGPathAddLineToPoint(path, NULL, 113.5, 187); 
CGPathAddLineToPoint(path, NULL, 113.5, 199); 
CGPathAddLineToPoint(path, NULL, 113.5, 193); 
CGPathAddLineToPoint(path, NULL, 113.5, 195); 
CGPathAddLineToPoint(path, NULL, 113.5, 194); 

CAKeyframeAnimation * 
animation = [CAKeyframeAnimation 
      animationWithKeyPath:@"position"]; 

[animation setPath:path]; 
[animation setDuration:1.5]; 
[animation setCalculationMode:kCAAnimationLinear]; 
NSArray *arr = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], 
[NSNumber numberWithFloat:0.12], 
[NSNumber numberWithFloat:0.24], 
[NSNumber numberWithFloat:0.36], 
[NSNumber numberWithFloat:0.48], 
[NSNumber numberWithFloat:0.60], 
[NSNumber numberWithFloat:0.72], 
[NSNumber numberWithFloat:0.84], 
[NSNumber numberWithFloat:1.0],nil]; 

[animation setKeyTimes:arr]; 
[animation setTimingFunctions:[NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
           [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], nil]]; 
//[animation setAutoreverses:YES]; 
CFRelease(path); 
return animation; 

}

- (void)monBtnIn { 

[monButton.layer setPosition:CGPointMake(113.5,194)]; 
[monButton.layer addAnimation:[self monInAnimation] 
        forKey:@"position"]; 

}

उत्तर

27

आपके लिए दो वैकल्पिक समाधान:

सबसे पहले, आप ट्रांसफॉर्म संपत्ति को भी एनिमेट कर सकते हैं।

ब्रैड के कोड का उपयोग करके, लेकिन कीपैथ के लिए @ "ट्रांसफॉर्म" का उपयोग करना। प्राथमिक लाभ जा रहा है आप वास्तविक फ्रेम गणना करने के लिए की जरूरत नहीं है कि है, लेकिन बजाय एक साधारण स्केलिंग कारक प्रदान करते हैं:

ऑब्जेक्टिव-सी:

CAKeyframeAnimation *boundsOvershootAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 

CATransform3D startingScale = CATransform3DScale (layer.transform, 0, 0, 0); 
CATransform3D overshootScale = CATransform3DScale (layer.transform, 1.2, 1.2, 1.0); 
CATransform3D undershootScale = CATransform3DScale (layer.transform, 0.9, 0.9, 1.0); 
CATransform3D endingScale = layer.transform; 

NSArray *boundsValues = [NSArray arrayWithObjects:[NSValue valueWithCATransform3D:startingScale], 
                [NSValue valueWithCATransform3D:overshootScale], 
                [NSValue valueWithCATransform3D:undershootScale], 
                [NSValue valueWithCATransform3D:endingScale], nil]; 
[boundsOvershootAnimation setValues:boundsValues]; 

NSArray *times = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0f], 
        [NSNumber numberWithFloat:0.5f], 
        [NSNumber numberWithFloat:0.9f], 
        [NSNumber numberWithFloat:1.0f], nil];  
[boundsOvershootAnimation setKeyTimes:times]; 


NSArray *timingFunctions = [NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
          nil]; 
[boundsOvershootAnimation setTimingFunctions:timingFunctions]; 
boundsOvershootAnimation.fillMode = kCAFillModeForwards; 
boundsOvershootAnimation.removedOnCompletion = NO; 

स्विफ्ट 4:

let boundsOvershootAnimation = CAKeyframeAnimation(keyPath: "transform") 

let startingScale = CATransform3DScale(layer.transform, 0, 0, 0) 
let overshootScale = CATransform3DScale(layer.transform, 1.2, 1.2, 1.0) 
let undershootScale = CATransform3DScale(layer.transform, 0.9, 0.9, 1.0) 
let endingScale = layer.transform 

boundsOvershootAnimation.values = [startingScale, overshootScale, undershootScale, endingScale] 

boundsOvershootAnimation.keyTimes = [0.0, 0.5, 0.9, 1.0].map { NSNumber(value: $0) } 

boundsOvershootAnimation.timingFunctions = [ 
    CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseOut), 
    CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut), 
    CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut) 
] 

boundsOvershootAnimation.fillMode = kCAFillModeForwards 
boundsOvershootAnimation.isRemovedOnCompletion = false 

दूसरा, और संभवतः आसान, मूल एनीमेशन के लिए एक ओपन सोर्स रैपर FTUtils का उपयोग कर रहा है। इसमें एक स्टॉक "वसंत" एनीमेशन शामिल है। http://github.com/neror/ftutils

+1

यह अच्छा काम करता है ... धन्यवाद। मैंने एक अवधि जोड़ा था। मैं एफटीयूटिलिस की जांच करूंगा - धन्यवाद। – Jonathan

+2

आप कीपैथ का उपयोग करके "transform.scale" के रूप में केवल संख्याओं का उपयोग कर सकते हैं। यही है ना ? –

4

मैं अगर तुम एक UIView के पैमाने एनिमेट के लिए एक CAKeyframeAnimation उपयोग कर सकते हैं पता नहीं है, लेकिन आप एक CABasicAnimation और स्थापित करने के साथ यह कर सकते हैं fromValue और toValue गुण, और बदलने संपत्ति चेतन करने के लिए है कि का उपयोग कर:

- (CAAnimation*)monInAnimation 
{ 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)]; 
    animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3.0, 3.0, 3.0)]; 
    [animation setDuration:1.5]; 
    [animation setAutoreverses:YES]; 
    return animation; 
} 

- (IBAction)monBtnIn 
{ 
    [monButton.layer addAnimation:[self monInAnimation] forKey:@"transform"]; 
} 
+1

धन्यवाद अकोस्मा! मैं स्केलिंग की कि जिस तरह से कोशिश की है, लेकिन मैं यह पता लगाने नहीं कर सकते कि कैसे अधिक से अधिक 2-फ़्रेम जोड़ना है। 'SetAutoreverses' के साथ यह फिर वापस ए मैं डी करने सेल्सियस के लिए बी को आप आप और अधिक 'fromValues' और 'ToValues' जोड़ सकते हैं, तो पता चलेगा कि एक से जाना चाहता हूँ के लिए बी को एक से चला जाता है? धन्यवाद CAAnimationGroup वर्ग पर एक नजर डालें – Jonathan

+0

। यह CAAnimation से विरासत, और इसके साथ आप "श्रृंखला" व्यक्तिगत CABasicAnimations कर सकते हैं, अपने स्वयं के fromValue और toValue के साथ प्रत्येक। क्या आप यह खोज सकते हैं? –

+0

स्क्रैच कि, मैं डॉक्स की जाँच की है और ऐसा लगता है कि एक CAAnimationGroup में एनिमेशन समवर्ती एक के बाद एक चलाए जा रहे हैं, नहीं। ओह। आपको अपने एनिमेशन के लिए प्रतिनिधियों को सेट करना चाहिए, और फिर पिछला एक समाप्त होने पर एक नई एनीमेशन शुरू करना चाहिए। –

8

आर अपने कैकेफ्रेमएनीमेशन के पथ को सेट करने से एथर, आप स्वयं कीफ्रेम सेट करना चाहेंगे। मैं एक परत की सीमा के आकार एनिमेट द्वारा एक "पॉप में" प्रभाव बना लिया है से पहले:

CAKeyframeAnimation *boundsOvershootAnimation = [CAKeyframeAnimation animationWithKeyPath:@"bounds.size"]; 
CGSize startingSize = CGSizeZero; 
CGSize overshootSize = CGSizeMake(targetSize.width * (1.0f + POPINOVERSHOOTPERCENTAGE), targetSize.height * (1.0f + POPINOVERSHOOTPERCENTAGE)); 
CGSize undershootSize = CGSizeMake(targetSize.width * (1.0f - POPINOVERSHOOTPERCENTAGE), targetSize.height * (1.0f - POPINOVERSHOOTPERCENTAGE)); 
NSArray *boundsValues = [NSArray arrayWithObjects:[NSValue valueWithCGSize:startingSize], 
         [NSValue valueWithCGSize:overshootSize], 
         [NSValue valueWithCGSize:undershootSize], 
         [NSValue valueWithCGSize:targetSize], nil]; 
[boundsOvershootAnimation setValues:boundsValues]; 

NSArray *times = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0f], 
        [NSNumber numberWithFloat:0.5f], 
        [NSNumber numberWithFloat:0.9f], 
        [NSNumber numberWithFloat:1.0f], nil];  
[boundsOvershootAnimation setKeyTimes:times]; 


NSArray *timingFunctions = [NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], 
          nil]; 
[boundsOvershootAnimation setTimingFunctions:timingFunctions]; 
boundsOvershootAnimation.fillMode = kCAFillModeForwards; 
boundsOvershootAnimation.removedOnCompletion = NO; 

जहां POPINOVERSHOOTPERCENTAGE अंश जिसके द्वारा मैं परत का लक्ष्य आकार लक्ष्य के पार चले जाना चाहते थे है।

+0

धन्यवाद ब्रैड। यह वास्तव में उस तरह का नियंत्रण है जिसके बाद मैं था। – Jonathan

12

transform.scale, किसी को भी:

आप इसे प्राप्त कर सकते हैं?

let anim = CAKeyframeAnimation(keyPath: "transform.scale") 
anim.values = [0, 1, 0, 1, 0, 1, 0] 
anim.duration = 4.0 

smallView.layer.addAnimation(anim, forKey: "what") 

पूरी तरह से असंबंधित, अगर आप वाला उपयोग मूल्यों सरणी में तैरता हैं, तो आप उन्हें NSNumbers के रूप में जोड़ना चाहिए, अन्यथा वे सिर्फ 0s के रूप में पहुंचते हैं!

anim.values = [0.0, 1.2, 0.9, 1.0].map { NSNumber(double: $0) } 
+0

मैं "ट्रांसफॉर्म" का उपयोग कर रहा था, लेकिन इससे 'rotationMode = kCAAnimationRotateAuto' के साथ समस्याएं आईं। "Transform.scale" का उपयोग करके मूल्य घोषणा को सरल बना दिया गया। बहुत धन्यवाद। – Henrik

संबंधित मुद्दे