2012-03-11 32 views
8

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

मेरे पास एक टेबल पर कार्ड का एक सेट है। चूंकि उपयोगकर्ता कार्ड के सेट को ऊपर या नीचे स्वाइप करता है, तालिका को ऊपर और नीचे ले जाता है। किसी भी समय स्क्रीन पर 4 कार्ड दिखाई दे रहे हैं, लेकिन केवल दूसरा कार्ड अपना चेहरा दिखा रहा है। चूंकि उपयोगकर्ता दूसरे कार्ड को अपने चेहरे पर वापस फिसलता है और अगला कार्ड (स्वाइप दिशा के आधार पर) इसके स्थान पर अपनी जगह दिखाता है।

मैं इस तरह मेरा कार्ड दृश्य वर्ग की स्थापना की है:

@interface WLCard : UIView { 
    UIView *_frontView; 
    UIView *_backView; 
    BOOL flipped; 
} 

और मैं कोड के इस टुकड़े का उपयोग कर कार्ड flipping की कोशिश की है:

- (void) flipCard { 
    [self.flipTimer invalidate]; 
    if (flipped){ 
     return; 
    } 

    id animationsBlock = ^{ 
      self.backView.alpha = 1.0f; 
      self.frontView.alpha = 0.0f; 
      [self bringSubviewToFront:self.frontView]; 
      flipped = YES; 

      CALayer *layer = self.layer; 
      CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; 
      rotationAndPerspectiveTransform.m34 = 1.0/500; 
      rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, M_PI, 1.0f, 0.0f, 0.0f); 
      layer.transform = rotationAndPerspectiveTransform; 
    }; 
    [UIView animateWithDuration:0.25 
          delay:0.0 
         options: UIViewAnimationCurveEaseInOut 
        animations:animationsBlock 
        completion:nil]; 

} 

इस कोड काम करता है, लेकिन यह निम्नलिखित है इसके साथ समस्याएं जिन्हें मैं समझ नहीं पा रहा हूं:

  1. एक्स-अक्ष में कार्ड का केवल आधा एनिमेटेड है।
  2. एक बार फ़्लिप हो जाने पर, कार्ड का चेहरा उल्टा और प्रतिबिंबित होता है।
  3. एक बार जब मैंने कार्ड फिसल दिया है तो मुझे एनीमेशन कभी भी फिर से चलाने के लिए नहीं मिल सकता है। दूसरे शब्दों में, मैं एनीमेशन ब्लॉक को जितनी बार चाहूं उतनी बार चला सकता हूं, लेकिन केवल पहली बार एनिमेट होगा। बाद के समय मैं सबव्यूज़ के बीच केवल एक फीका में और बाहर जाने के लिए एनिमेट करने की कोशिश करता हूं।

इसके अलावा, ध्यान रखें कि मुझे कार्ड के चेहरे से बातचीत करने में सक्षम होना चाहिए। यानी इसके पास बटन हैं।

यदि कोई इन मुद्दों में भाग लेता है तो आपके समाधान देखना अच्छा होगा। यथार्थवाद के अतिरिक्त बिट को देने के लिए एनीमेशन में एक परिप्रेक्ष्य परिवर्तन को जोड़ना बेहतर होगा।

उत्तर

11

यह मेरे विचार से आसान तरीका साबित हुआ और मुझे प्रभाव प्राप्त करने के लिए किसी भी कोरएनीमेशन पुस्तकालयों का उपयोग करने की आवश्यकता नहीं थी। सुराग के लिए @Aaron Hayman के लिए धन्यवाद। मैं transitionWithView:duration:options:animations:completion

कंटेनर दृश्य के अंदर मेरे कार्यान्वयन प्रयोग किया है:

[UIView transitionWithView:self 
         duration:0.2 
         options:UIViewAnimationOptionTransitionFlipFromBottom 
        animations: ^{ 
          [self.backView removeFromSuperview]; 
          [self addSubview:self.frontView]; 
        } 
        completion:NULL]; 

चाल UIViewAnimationOptionTransitionFlipFromBottom विकल्प था। संयोग से, ऐप्पल के पास उनके दस्तावेज़ में कोड का सटीक बिट है। आप ब्लॉक में अन्य एनिमेशन जोड़ सकते हैं जैसे आकार बदलने और आगे बढ़ना।

2

ठीक है, यह एक पूर्ण समाधान नहीं होगा लेकिन मैं कुछ चीजों को इंगित करूंगा जो सहायक हो सकते हैं। मैं कोर-एनीमेशन गुरु नहीं हूं लेकिन मैंने अपने कार्यक्रम में कुछ 3 डी रोटेशन किए हैं।

सबसे पहले, किसी दृश्य में 'बैक' नहीं है। तो यदि आप एमएफआई (180 डिग्री) द्वारा कुछ घुमाते हैं तो आप उस दृश्य को देखने के लिए जा रहे हैं जैसे कि पीछे से (यही कारण है कि यह उल्टा/प्रतिबिंबित है)।

x- अक्ष के पार कार्ड का केवल आधा एनिमेटेड है:

मुझे यकीन है कि आप द्वारा क्या मतलब है नहीं कर रहा हूँ।

लेकिन, यह आपके एंकर पॉइंट पर विचार करने में मदद कर सकता है (जिस बिंदु पर रोटेशन होता है)। यह आमतौर पर केंद्र में होता है, लेकिन अक्सर आपको इसे अन्यथा होने की आवश्यकता होती है। ध्यान दें कि एंकर पॉइंट अनुपात (प्रतिशत/100) के रूप में व्यक्त किए जाते हैं ... इसलिए मान 0 - 1.0f हैं। आपको केवल इसे एक बार सेट करने की आवश्यकता है (जब तक आपको इसे बदलने की आवश्यकता न हो)। यहां आपके द्वारा लंगर बिंदु तक पहुँच गया है:

layer.anchorPoint = CGPointMake(0.5f, 0.5f) //This is center

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

यदि आप एक दृश्य से दूसरे में एनिमेट कर रहे हैं (और आप [UIView transitionWithView:duration:options:animations:completion:]; का उपयोग नहीं कर सकते हैं) तो आपको दो स्टेज एनीमेशन का उपयोग करना होगा। एनीमेशन के पहले चरण में, 'कार्ड' के लिए जो पीछे की तरफ फ़्लिप किया जा रहा है, आप दृश्य-से-गायब हो जाएंगे 'ऊपर/नीचे/जो भी' M_PI_2 पर (जिस बिंदु पर यह 'चला गया' होगा, या इसके घूर्णन के कारण दिखाई नहीं दे रहा है)। और दूसरे चरण में, आप 0 के पीछे-पीछे-देखने-गायब हो जाते हैं (जो पहचान परिवर्तन होना चाहिए ... उर्फ, दृश्य सामान्य स्थिति)। इसके अलावा, आपको दिखाई देने वाले 'कार्ड' के लिए सटीक विपरीत करना होगा (फ़्रोंसाइड के लिए)। आप इसे पहले के समापन ब्लॉक में [UIView animateWithDuration:...] लागू करके ऐसा कर सकते हैं। हालांकि मैं आपको चेतावनी दूंगा, ऐसा करने से थोड़ा जटिल हो सकता है। खासकर जब से आप 'बैकसाइड' के विचारों को देखना चाहते हैं, जो मूल रूप से 4 विचारों को एनिमेट करने की आवश्यकता होगी (दृश्य-से-गायब हो जाना, दृश्य-से-प्रकट, पीछे-पीछे-देखने-गायब होना, और पीछे की ओर- के देखने-टू-दिखाई देते हैं)। आखिरकार, दूसरी एनीमेशन के समापन ब्लॉक में आप कुछ क्लीनअप कर सकते हैं (रीसेट व्यू जो घुमाए गए हैं और अपना अल्फा 0.0 एफ आदि बनाते हैं ...)।

मुझे पता है कि यह जटिल है, इसलिए आप कोर-एनीमेशन पर कुछ ट्यूटोरियल पढ़ना चाहेंगे।

+0

धन्यवाद हारून दिखाएगा। संक्रमण WithView विधि ने मुझे समाधान के लिए एक सुराग दिया है। ऐसा कहा जा रहा है, आपने मुझे 3 डी एनिमेशन के बारे में बेहतर समझ दी है। एक अच्छा कोर एनीमेशन पुस्तक में निवेश करने के लिए मेरे लिए समय। –

1

@Aaron की कुछ अच्छी जानकारी है जिसे आपको पढ़ना चाहिए।

सबसे आसान समाधान CATransformLayer का उपयोग करना है जो आपको अन्य CALayer के अंदर रखने और उनके 3 डी पदानुक्रम को बनाए रखने की अनुमति देगा।

उदाहरण एक "कार्ड" एक सामने है कि बनाने के लिए के लिए और वापस तुम कर सकते हो कुछ इस तरह:

CATransformLayer *cardContainer = [CATransformLayer layer]; 
cardContainer.frame = // some frame; 

CALayer *cardFront = [CALayer layer]; 
cardFront.frame  = cardContainer.bounds; 
cardFront.zPosition = 2; // Higher than the zPosition of the back of the card 
cardFront.contents = (id)[UIImage imageNamed:@"cardFront"].CGImage; 
[cardContainer addSublayer:cardFront]; 

CALayer *cardBack = [CALayer layer]; 
cardBack.frame  = cardContainer.bounds; 
cardBack.zPosition = 1; 
cardBack.contents = (id)[UIImage imageNamed:@"cardBack"].CGImage; // You may need to mirror this image 
[cardContainer addSublayer:cardBack]; 
इस के साथ

अब आप आवेदन कर सकते हैं अपने cardContainer को बदलने और एक flipping कार्ड है।

+0

जबकि यह विधि काम करेगी।मुझे कार्ड पर इंटरैक्टिव तत्वों के साथ UIViews की आवश्यकता है क्योंकि उपयोगकर्ता को कार्ड चेहरे से बातचीत करने की आवश्यकता है। कैलायर का उपयोग करने से मुझे छवियों आदि के साथ काम करने की इजाजत मिलती है। –

+0

इस पदानुक्रम को एक 'UIView' में रखें जो इंटरैक्शन से निपटेंगे ... –

+0

आह। का उल्लेख किया। ऐसा लगता है कि काम करना चाहिए। धन्यवाद। –

0

@ Paul.s

मैं कार्ड कंटेनर के साथ अपने दृष्टिकोण का पालन किया लेकिन जब मैं applt कार्ड कंटेनर पर रोटेशन एनीमेशन ही चारों ओर पहले कार्ड घूमता का केवल एक आधा और अंत में पूरे दृश्य appears.Each समय एक तरफ एनीमेशन

0

Paul.s इस आधार पर में याद आ रही है स्विफ्ट 3 के लिए अद्यतन किया जाता है और एक कार्ड तिरछे फ्लिप जाएगा:

func createLayers(){ 
    transformationLayer = CATransformLayer(layer: CALayer()) 
    transformationLayer.frame = CGRect(x: 15, y: 100, width: view.frame.width - 30, height: view.frame.width - 30) 

    let black = CALayer() 
    black.zPosition = 2 
    black.frame = transformationLayer.bounds 
    black.backgroundColor = UIColor.black.cgColor 

    transformationLayer.addSublayer(black) 

    let blue = CALayer() 
    blue.frame = transformationLayer.bounds 
    blue.zPosition = 1 
    blue.backgroundColor = UIColor.blue.cgColor 

    transformationLayer.addSublayer(blue) 

    let tgr = UITapGestureRecognizer(target: self, action: #selector(recTap)) 
    view.addGestureRecognizer(tgr) 
    view.layer.addSublayer(transformationLayer) 
} 

एनिमेट एक पूर्ण 360 लेकिन जब से परतों अलग zPositions अलग है परतों के 'पक्ष'

func recTap(){ 
    let animation = CABasicAnimation(keyPath: "transform") 
    animation.delegate = self 
    animation.duration = 2.0 
    animation.fillMode = kCAFillModeForwards 
    animation.isRemovedOnCompletion = false 
    animation.toValue = NSValue(caTransform3D: CATransform3DMakeRotation(CGFloat(Float.pi), 1, -1, 0)) 
    transformationLayer.add(animation, forKey: "arbitrarykey") 
    }