2010-07-19 16 views
7

मैं यह समझने की कोशिश कर रहा हूं कि मेरी एनीमेशन में क्या गलत है और मुझे अभी भी इसका पता नहीं लगा है। मुझे लगता है कि यह वास्तव में सीधे आगे होना चाहिए, लेकिन संभवतः कुछ उदाहरण और दस्तावेज़ीकरण पढ़ने के बाद भी मुझे कुछ याद आ रही है।CABasicAnimation मेरी संपत्ति को एनिमेट नहीं कर रहा है

मेरी समस्या मूल रूप से इस तथ्य का निर्माण करती है कि आईफोन पर, आप परतों को स्वचालित रूप से आकार में नहीं देख सकते हैं (दृश्य के साथ)। प्रलेखन अन्यथा कहता है लेकिन एसडीके में परत के लिए कोई ऑटोरेसाइजमास्क नहीं है। इसलिए मैंने थोड़ा कामकाज करने और परत को एनिमेट करने का फैसला किया।

मुझे कोड का यह सरल टुकड़ा मिला है जो एक साधारण आकार बदलने वाली एनीमेशन करना चाहिए। मान अच्छे हैं और अगर मैं एनिम स्टार्ट/एंड का पता लगाने के लिए प्रतिनिधि को भी सेट करता हूं।

// I've got a property named layerImage (which is a CALayer) 
- (void)animateTestWithFrame:(CGRect)value { 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"layerImage.frame"]; 
    animation.duration = 1; 
    animation.fromValue = [NSValue valueWithCGRect:self.frame]; 
    animation.toValue = [NSValue valueWithCGRect:value]; 
    animation.removedOnCompletion = YES; 
    animation.delegate = self; 

    [self.layer addAnimation:animation forKey:@"layerImage.frame"]; 
} 

तो, कोई विचार?

--- संपादित करें ---

यह है कि फ्रेम लगता है CABasicAnimation और नाम के माध्यम से animatable नहीं (यह मानना ​​है कि कोड शामिल विंडो के एक subview के subview है कि अगर एक फर्क कर सकता है) संपत्ति "फ्रेम"। सीमाओं का उपयोग करते समय, मुझे कुछ अजीब परिणाम मिल गया है, लेकिन कम से कम मुझे कुछ मिल रहा है। इस पर जांच जारी रखेंगे।

उत्तर

26

तो यह अच्छा है कि आपने यहां चीजों को समझ लिया है, लेकिन आपके अपने प्रश्न के उत्तर में कुछ त्रुटियां हैं। मुझे कुछ चीजों को सही करने दें:

फ्रेम गुण एनिमेटेड हो सकता है - बस स्पष्ट एनीमेशन के साथ नहीं। आप एक दृश्य की जड़ परत के अलावा किसी अन्य परत के लिए निम्न करते हैं, फ्रेम ठीक चेतन जाएगा:

[CATransaction begin]; 
[CATransaction setAnimationDuration:2.0f]; 
[animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)]; 
[CATransaction commit]; 

याद रखें कि एक परत पर एक संपत्ति की स्थापना डिफ़ॉल्ट से है कि संपत्ति परिवर्तन चेतन होगा। वास्तव में आपको संपत्ति परिवर्तन पर एनिमेशन अक्षम करना होगा यदि आप इसे एनिमेट नहीं करना चाहते हैं। (बेशक यह केवल तभी सच है यदि आप दृश्य की मूल परत के अलावा एक परत को एनिमेट कर रहे हैं।) यदि आप एक स्पष्ट एनीमेशन का उपयोग करने की आवश्यकता है तो आप दोनों स्थिति और सीमाओं को एनिमेट करने में सही हैं।

आप एक UIView पर फ्रेम निहित एनीमेशन का उपयोग कर चेतन कर सकते हैं:

[UIView beginAnimations:nil context:NULL]; 
[UIView setAnimationDuration:3.0f]; 
[[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)]; 
[UIView commitAnimations]; 

यह दृश्य के वर्तमान फ्रेम से चेतन (सीमा और स्थिति) एक्स = 45.0, y = 45.0, w = 100.0 करने के लिए , एच = 100.0।

ऐसा लगता है कि आप एनीमेशन और परत के बीच के अंतर को भी गलत समझ सकते हैं। आप परतों में एनिमेशन जोड़ते हैं, लेकिन एक परत में एनीमेशन जोड़ना स्वचालित रूप से उस संपत्ति को सेट नहीं करता है जिसे आप एनिमेट कर रहे हैं।

कैलियर मॉडल ऑब्जेक्ट्स हैं। उनमें उस परत के बारे में जानकारी होती है जो अंततः स्क्रीन पर प्रदान की जाती है। आप एक परत की संपत्ति सेट कर सकते हैं यदि आप उस संपत्ति को वास्तव में उस मान में रखना चाहते हैं। यदि आप केवल संपत्ति को एनिमेट करते हैं, तो यह केवल एक दृश्य प्रतिनिधित्व होगा और वास्तविक नहीं होगा - यही कहना है कि यह मान परत के मूल मूल्य पर वापस आ जाता है क्योंकि आपने वास्तव में इसे कभी नहीं बदला है।

जो मुझे अगले बिंदु पर ले जाता है। आप ने कहा:

उपयोग "animation.removedOnCompletion = नहीं; animation.fillMode = kCAFillModeForwards," यह सुनिश्चित करें कि मूल्यों एनीमेशन

इस के अंत पर reseted नहीं कर रहे हैं वास्तव में सही नहीं है। ये दो मान एनीमेशन को अंतिम स्थिति दृष्टि से पर बने रहने का कारण बनते हैं, हालांकि, परत के वास्तविक मान परिवर्तित नहीं हुए हैं। वे अभी भी सटीक वही मान हैं जब आप एनीमेशन शुरू करते थे। सामान्य रूप से (कुछ अपवादों के साथ) आप इन दो पैरामीटर का उपयोग नहीं करना चाहते हैं क्योंकि वे दृश्य केवल हैं। आप जो चाहते हैं वह वास्तव में उस संपत्ति के लिए परत मान सेट करना है जिसे आप एनिमेट कर रहे हैं।

कहें, उदाहरण के लिए, कि आप एक स्पष्ट एनीमेशन का उपयोग करके अपनी परत की स्थिति को एनिमेट करना चाहते हैं। यहां वह कोड है जो आप चाहते हैं:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; 
[animation setFromValue:[NSValue valueWithCGPoint:CGPointMake(70.0f, 70.0f)]]; 
[animation setToValue:[NSValue valueWithCGPoint:CGPointMake(150.0f, 150.0f)]]; 
[animation setDuration:2.0f]; 

// Actually set the position on the *layer* that you want it to be 
// when the animation finishes. 
[animationLayer setPosition:CGPointMake(150.0f, 150.0f)]; 

// Add the animation for the position key to ensure that you 
// override the animation for position changes with your animation. 
[animationLayer addAnimation:animation forKey:@"position"]; 

आप एनीमेशन समूह पर भी विचार करना चाहेंगे। एक एनीमेशन समूह के साथ, आप कई एनिमेशन एक साथ समूहित कर सकते हैं और फिर नियंत्रित कर सकते हैं कि वे एक दूसरे से कैसे संबंधित हैं।आपके मामले में आपकी सीमाओं और स्थिति एनिमेशन के लिए अवधि समान है और इसलिए आप जो करने की कोशिश कर रहे हैं वह समूह के बिना ठीक काम करेगा, लेकिन यदि आप एनिमेशन की शुरुआत को ऑफ़सेट करना चाहते हैं, उदाहरण के लिए आप स्थिति नहीं चाहते थे फ्रेम एनीमेशन में एक या दो सेकंड तक शुरू करने के लिए एनीमेशन, आप स्टार्टटाइम स्थिति एनीमेशन के मान को सेट करके उन्हें रोक सकते हैं।

अंत में, मुझे यह जानकर उत्सुकता होगी कि आप UIView पर उपलब्ध निहित एनिमेशन का उपयोग क्यों नहीं कर सके। मैं कोर एनीमेशन कोड के विशाल बहुमत में इनका उपयोग करता हूं और यह नहीं देख सकता कि यह आपकी स्थिति के लिए क्यों काम नहीं करेगा।

सर्वश्रेष्ठ संबंध।

+0

धन्यवाद। लेकिन UIView एनीमेशन समस्या के लिए, यह केवल मेरी परत से संबंधित था। आमतौर पर, मुझे UIView का उपयोग करके एनीमेशन के साथ कोई समस्या नहीं है, लेकिन मेरे मामले में यह अजीब व्यवहार कर रहा था। दृश्य फ्रेम का आकार बदलना आईफोन पर परत का आकार नहीं लेता है (क्योंकि आईफोन पर कोई स्वचालित तंत्र नहीं है, केवल विचारों और सबव्यू के लिए)। तो, आपको इसे "मैन्युअल रूप से" करना है। – Sauleil

+0

अच्छा जवाब! अधिक विस्तृत। अगर मैं कर सकता तो मैं आपको 2 अंक देता। – Soberman

3

मुख्य पथ केवल संपत्ति का मुख्य मार्ग होना चाहिए, न कि ऑब्जेक्ट का नाम भी।

उपयोग इस

[CABasicAnimation animationWithKeyPath:@"frame"] 
बजाय

इस

[CABasicAnimation animationWithKeyPath:@"layerImage.frame"] 

और बस Btw, जब आप एक परत को एनीमेशन जोड़ने के लिए, कुंजी doen't चेतन करने के लिए महत्वपूर्ण संपत्ति मतलब है। बस कुंजी (नाम) जिसे आप इस एनीमेशन को चाहते हैं (यह आपके कोड की अंतिम पंक्ति को संदर्भित करता है)

+0

फ्रेम के लिए ठीक है, लेकिन CABasicAnimation जानता है कि कौन सी परत उस संपत्ति को एनिमेट करने के लिए है? क्या इसका मतलब है कि मुझे करना है [layerImage addAnimation: एनीमेशन ...]। (कोशिश की और यह काम नहीं करता) – Sauleil

+0

यदि आप स्वयं (उस विधि में) से अलग ऑब्जेक्ट पर एनीमेशन कर रहे हैं, तो बस [self.layerImage.layer addAnimation: एनीमेशन ...] – tadejsv

+0

एक और बात: I समझ में नहीं आता कि आप यहां CABasicAnimation का उपयोग क्यों कर रहे हैं। UIView के एनिमेशन करेंगे। – tadejsv

1

तो, समाधान को "सीमा" और परत की "स्थिति" को एनिमेट करना था क्योंकि फ्रेम आईफोन पर एनिमेटेबल नहीं है। मुझे यह समझने में कुछ समय लगा कि स्थिति परत का केंद्र था और सीमाओं का आकार केंद्र से विस्तारित था, लेकिन यह आसान हिस्सा था।

तो, क्या मैं फिर से शुरू में किया था:

  1. setFrame में, सीमा और स्थिति संपत्ति के साथ 2 एनिमेशन बनाने।
  2. "एनीमेशन.removedOnCompletion = NO; एनीमेशन.फिलमोड = केसीएफिलमोड फॉरवर्ड;" का प्रयोग करें। यह सुनिश्चित करने के लिए कि एनीमेशन
  3. के अंत में मूल्यों को रीसेट नहीं किया गया है, "एनीमेशनडिडस्टॉप: समाप्त:" लागू करने के लिए प्रतिनिधि को स्वयं पंजीकृत करें। ऐसा लगता है कि आपको अभी भी मान सेट करने की आवश्यकता है: "layerImage.bounds = [animation.toValue CGRectValue]; layerImage.position = [animation.toValue CGPointValue];"।

मैं UIView एनीमेशन सिस्टम का उपयोग सीधे करने में सक्षम नहीं था क्योंकि यह परतों पर जो भी चाहता था वह नहीं कर रहा था।

धन्यवाद tadej5553 मुझे "addAnimation" के साथ परत समस्या को इंगित करने के लिए धन्यवाद। तो यहां उन लोगों के लिए कोड है जो देखना चाहते हैं कि यह कैसा दिखता है।

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 
    CABasicAnimation *animation = (CABasicAnimation*)anim; 

    if ([animation.keyPath isEqualToString:@"bounds"]) { 
     layerImage.bounds = [animation.toValue CGRectValue]; 
    } else if ([animation.keyPath isEqualToString:@"position"]) { 
     layerImage.position = [animation.toValue CGPointValue]; 
    } 
} 

- (void)setFrame:(CGRect)value { 
    CGRect bounds = CGRectMake(0, 0, value.size.width, value.size.height); 

    if ([UIView isAnimationStarted]) { 
     // animate the bounds 
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"]; 
     animation.duration = [UIView animationDuration]; 
     animation.fromValue = [NSValue valueWithCGRect:layerImage.bounds]; 
     animation.toValue = [NSValue valueWithCGRect:bounds]; 
     animation.removedOnCompletion = NO; 
     animation.fillMode = kCAFillModeForwards; 
     animation.timingFunction = [UIView animationFunction]; 
     animation.delegate = self; 
     [layerImage addAnimation:animation forKey:@"BoundsAnimation"]; 

     // animate the position so it stays at 0, 0 of the frame. 
     animation = [CABasicAnimation animationWithKeyPath:@"position"]; 
     animation.duration = [UIView animationDuration]; 
     animation.fromValue = [NSValue valueWithCGPoint:layerImage.position]; 
     animation.toValue = [NSValue valueWithCGPoint:CGPointMake(bounds.size.width/2, bounds.size.height/2)]; 
     animation.removedOnCompletion = NO; 
     animation.fillMode = kCAFillModeForwards; 
     animation.timingFunction = [UIView animationFunction]; 
     animation.delegate = self; 
     [layerImage addAnimation:animation forKey:@"PositionAnimation"]; 
    } else { 
     layerImage.frame = bounds; 
    } 

    [super setFrame:value]; 
} 
संबंधित मुद्दे