CABasicAnimation এনিমেশন সম্পূর্ণ হওয়ার পরে প্রাথমিক মানটিতে পুনরায় সেট হয়


143

আমি একটি কালায়ার ঘুরছি এবং এনিমেশন শেষ হওয়ার পরে এটির চূড়ান্ত অবস্থানে থামানোর চেষ্টা করছি।

অ্যানিমেশন সম্পূর্ণ হওয়ার পরে এটি তার প্রাথমিক অবস্থানে পুনরায় সেট করে।

(এক্সকোড ডক্স স্পষ্টভাবে বলে যে অ্যানিমেশনটি সম্পত্তিটির মূল্য আপডেট করবে না))

এটি অর্জন করার জন্য কোনও পরামর্শ।


1
এটি এমন এক অদ্ভুত এসও প্রশ্নগুলির মধ্যে যেখানে উত্তরগুলির প্রায় সমস্তই সম্পূর্ণ ভুল just কেবল সম্পূর্ণ ভুল । আপনি খুব সহজেই .presentation()"চূড়ান্ত, দেখা" মান পেতে তাকান । নীচের সঠিক উত্তরগুলির জন্য অনুসন্ধান করুন যা উপস্থাপনা স্তরটি দিয়ে এটি সম্পন্ন করে ব্যাখ্যা করে।
ফ্যাটি

উত্তর:


285

উত্তরটি এখানে দেওয়া হয়েছে, এটি আমার উত্তর এবং কৃষ্ণণের মিশ্রণ।

cabasicanimation.fillMode = kCAFillModeForwards;
cabasicanimation.removedOnCompletion = NO;

ডিফল্ট মান kCAFillModeRemoved। (আপনি যে রিসেট আচরণটি দেখছেন তা কী।)


6
এটি সম্ভবত সঠিক উত্তর নয় - কৃষ্ণণের উত্তরের মন্তব্য দেখুন। আপনার সাধারণত এটি এবং কৃষ্ণনের প্রয়োজন হয়; শুধু একটি বা অন্য কাজ করবে না।
আদম

19
এটি সঠিক উত্তর নয়, নীচে @ ল্যাসি গডউইনের উত্তর দেখুন।
চিহ্নিত করুন

6
@ লেসলির সমাধানটি আরও ভাল কারণ এটি স্তরটিতে চূড়ান্ত মান সঞ্চয় করে না এনিমেশনে নয়।
ম্যাথিউ রউইফ

1
আপনি সরানোঅনুষ্ঠানটি কোনটিতে সেট করার সময় সতর্ক হন। আপনি যদি অ্যানিমেশন প্রতিনিধিটিকে "স্ব" তে অর্পণ করেন, আপনার অ্যানিমেশনটি অ্যানিমেশন দ্বারা ধরে রাখা হবে। সুতরাং, অপসারণের কল থেকেFromSuperview যদি আপনি নিজের দ্বারা অ্যানিমেশনটি সরিয়ে / ধ্বংস করতে ভুলে যান তবে উদাহরণস্বরূপ ডেলোক কল হবে না। আপনার একটি স্মৃতি ফাঁস হবে।
এমরাহগুন্দুজ

1
এই 200+ পয়েন্ট উত্তর সম্পূর্ণ, সম্পূর্ণ, সম্পূর্ণ ভুল।
ফ্যাটি

83

অপসারণযুক্ত সমস্যাটি হল ইউআই উপাদানটি ব্যবহারকারীর ইন্টারঅ্যাকশনকে মঞ্জুরি দেয় না।

আমি কৌশলটি হ'ল অ্যানিমেশনটিতে FROM মান এবং অবজেক্টে TO মান সেট করা। অ্যানিমেশনটি শুরুর আগে TO মানটি স্বয়ংক্রিয়ভাবে পূরণ করবে এবং এটি সরিয়ে ফেলা হলে অবজেক্টটিকে তার সঠিক অবস্থানে ছেড়ে দেবে।

// fade in
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath: @"opacity"];
alphaAnimation.fillMode = kCAFillModeForwards;

alphaAnimation.fromValue = NUM_FLOAT(0);
self.view.layer.opacity = 1;

[self.view.layer addAnimation: alphaAnimation forKey: @"fade"];

7
আপনি যদি কোনও সূচনা বিলম্ব সেট করেন তবে কাজ করে না। যেমন alphaAnimation.beginTime = 1; , fillModeআমি যতদূর বলতে পারি প্রয়োজনের প্রয়োজন নেই ...?
স্যাম

অন্যথায়, এটি একটি ভাল উত্তর, স্বীকৃত উত্তর অ্যানিমেশন শেষ হওয়ার পরে কোনও মান পরিবর্তন করতে দেয় না ...
স্যাম

2
আমার এটিও লক্ষ্য করা উচিত যে beginTimeএটি আপেক্ষিক নয়, আপনার যেমন ব্যবহার করা উচিত:CACurrentMediaTime()+1;
স্যাম

এটি 'এটি' এটি "এটি" নয় - এর-not-its.info। দুঃখিত যদি এটি কেবল একটি টাইপ ছিল।
ফতুহোকু


16

নিম্নলিখিত সম্পত্তি সেট করুন:

animationObject.removedOnCompletion = NO;

@ নীলেশ: আপনার উত্তর গ্রহণ করুন। এটি অন্যান্য এসও ব্যবহারকারীদের আপনার উত্তরের উপর আস্থা রাখবে।
কৃষ্ণন

7
আমাকে .ফিলমোড = কেসিএফিলমোড ফোরওয়ার্ড এবং। রেমোভডনকম্প্লেশন = না উভয়ই ব্যবহার করতে হয়েছিল। ধন্যবাদ!
উইলিয়াম জং

12

এটি আপনার কোডের ভিতরে রাখুন

CAAnimationGroup *theGroup = [CAAnimationGroup animation];

theGroup.fillMode = kCAFillModeForwards;

theGroup.removedOnCompletion = NO;

12

আপনি যখন এটিকে স্তরটিতে যুক্ত CABasicAnimationকরবেন positionতখন আপনি কীটির কী সেট করতে পারবেন । এটি করে এটি রান লুপের বর্তমান পাসের পজিশনে সম্পন্ন অন্তর্নিহিত অ্যানিমেশনটিকে ওভাররাইড করবে।

CGFloat yOffset = 30;
CGPoint endPosition = CGPointMake(someLayer.position.x,someLayer.position.y + yOffset);

someLayer.position = endPosition; // Implicit animation for position

CABasicAnimation * animation =[CABasicAnimation animationWithKeyPath:@"position.y"]; 

animation.fromValue = @(someLayer.position.y);
animation.toValue = @(someLayer.position.y + yOffset);

[someLayer addAnimation:animation forKey:@"position"]; // The explicit animation 'animation' override implicit animation

আপনার কাছে 2011 অ্যাপল ডাব্লুডাব্লুডিসি ভিডিও সেশন 421 - কোর অ্যানিমেশন প্রয়োজনীয়তা (ভিডিওর মাঝামাঝি) সম্পর্কিত আরও তথ্য থাকতে পারে


1
এটি এটি করার সঠিক পদ্ধতির মতো দেখায়। অ্যানিমেশন স্বাভাবিকভাবেই মুছে ফেলা হবে (ডিফল্ট), এবং একবার অ্যানিমেশন সম্পূর্ণ না, এটা মানগুলি সেট সামনে অ্যানিমেশন শুরু বিশেষভাবে এই লাইন ফিরে: someLayer.position = endPosition;। এবং ডাব্লুডাব্লুডিসিতে রেফের জন্য ধন্যবাদ!
bauerMusic

10

একটি কালায়ারের একটি মডেল স্তর এবং উপস্থাপনা স্তর থাকে। একটি অ্যানিমেশন চলাকালীন, উপস্থাপনা স্তরটি মডেলটির থেকে স্বাধীনভাবে আপডেট হয়। অ্যানিমেশনটি সম্পূর্ণ হয়ে গেলে, উপস্থাপনা স্তরটি মডেল থেকে মান সহ আপডেট করা হয়। অ্যানিমেশনটি শেষ হওয়ার পরে যদি আপনি কোনও ঝাঁকুনি দেওয়া লাফ এড়াতে চান তবে কীটি হ'ল দুটি স্তরকে সিঙ্ক করে রাখা।

যদি আপনি শেষ মানটি জানেন তবে আপনি সরাসরি মডেলটি সেট করতে পারেন।

self.view.layer.opacity = 1;

তবে আপনার যদি এমন অ্যানিমেশন থাকে যেখানে আপনি শেষ অবস্থানটি জানেন না (উদাহরণস্বরূপ একটি ধীর বিবর্ণ যা ব্যবহারকারী বিরতি দিতে পারে এবং তারপরে বিপরীত হতে পারে), তবে আপনি বর্তমান মানটি সন্ধানের জন্য সরাসরি উপস্থাপনা স্তরটি জিজ্ঞাসা করতে পারেন, এবং তারপরে মডেলটি আপডেট করুন।

NSNumber *opacity = [self.layer.presentationLayer valueForKeyPath:@"opacity"];
[self.layer setValue:opacity forKeyPath:@"opacity"];

উপস্থাপনা স্তর থেকে মানটি টানানো বিশেষত স্কেলিং বা ঘূর্ণন কীপ্যাথগুলির জন্যও কার্যকর। (যেমন transform.scale, transform.rotation)


8

ব্যবহার না করে removedOnCompletion

আপনি এই কৌশলটি চেষ্টা করতে পারেন:

self.animateOnX(item: shapeLayer)

func animateOnX(item:CAShapeLayer)
{
    let endPostion = CGPoint(x: 200, y: 0)
    let pathAnimation = CABasicAnimation(keyPath: "position")
    //
    pathAnimation.duration = 20
    pathAnimation.fromValue = CGPoint(x: 0, y: 0)//comment this line and notice the difference
    pathAnimation.toValue =  endPostion
    pathAnimation.fillMode = kCAFillModeBoth

    item.position = endPostion//prevent the CABasicAnimation from resetting item's position when the animation finishes

    item.add(pathAnimation, forKey: nil)
}

3
এটি সেরা কার্যকরী উত্তর বলে মনে হচ্ছে
রাম্বোসা

একমত। @ আয়মানের মন্তব্যটি নোট করুন যে আপনাকে .fromValue সম্পত্তিটি শুরু মানের থেকে সংজ্ঞা দিতে হবে । অন্যথায়, আপনি মডেলটিতে প্রারম্ভিক মানটি ওভাররাইট করে ফেলেছেন এবং অ্যানিমেশন থাকবে।
জেফ কলিয়ার

এই এক এবং @ জেসন-মুরের উত্তর গৃহীত উত্তরের চেয়ে ভাল। গৃহীত উত্তরে অ্যানিমেশনটি কেবল বিরতি দেওয়া হয়েছে তবে নতুন মানটি আসলে সম্পত্তিটিতে সেট করা নেই। এর ফলে অযাচিত আচরণ হতে পারে।
লাকা

8

সুতরাং আমার সমস্যাটি হ'ল আমি প্যানের অঙ্গভঙ্গিতে কোনও বস্তুর ঘোরানোর চেষ্টা করছিলাম এবং তাই প্রতিটি পদক্ষেপে আমার একাধিক অভিন্ন অ্যানিমেশন ছিল। আমার উভয় ছিল fillMode = kCAFillModeForwardsএবং isRemovedOnCompletion = falseএটি কোনও উপকারে আসেনি। আমার ক্ষেত্রে, আমাকে নিশ্চিত করতে হয়েছিল যে আমি যখনই নতুন অ্যানিমেশন যুক্ত করি তখন অ্যানিমেশন কীটি আলাদা হয় :

let angle = // here is my computed angle
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.toValue = angle
rotate.duration = 0.1
rotate.isRemovedOnCompletion = false
rotate.fillMode = CAMediaTimingFillMode.forwards

head.layer.add(rotate, forKey: "rotate\(angle)")

7

সহজভাবে সেট করা fillModeএবং removedOnCompletionআমার জন্য কাজ করে না। আমি নীচের সমস্ত বৈশিষ্ট্যকে CabasicAnimation অবজেক্টে সেট করে সমস্যার সমাধান করেছি :

CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.duration = 0.38f;
ba.fillMode = kCAFillModeForwards;
ba.removedOnCompletion = NO;
ba.autoreverses = NO;
ba.repeatCount = 0;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.85f, 0.85f, 1.0f)];
[myView.layer addAnimation:ba forKey:nil];

এই কোডটি myViewএর আকারের 85% (তৃতীয় মাত্রা আনলটার্ড) এ রূপান্তরিত করে।


7

কোর অ্যানিমেশন দুটি স্তরের স্তরক্রম বজায় রাখে: মডেল স্তর এবং উপস্থাপনা স্তর । যখন অ্যানিমেশনটি চলছে, মডেল স্তরটি আসলে অক্ষত থাকে এবং এটি প্রাথমিক মান রাখে initial ডিফল্টরূপে, অ্যানিমেশনটি শেষ হয়ে গেলে এটি সরিয়ে ফেলা হয়। তারপরে উপস্থাপনা স্তরটি মডেল স্তরের মানটিতে ফিরে আসে।

সহজভাবে সেট removedOnCompletionকরার NOঅর্থ অ্যানিমেশনটি সরানো হবে না এবং মেমরির অপচয় করবে। তদ্ব্যতীত, মডেল স্তর এবং উপস্থাপনা স্তর আর সিঙ্ক্রোনাস হবে না, যা সম্ভাব্য বাগগুলি নিয়ে যেতে পারে।

সুতরাং মডেল স্তরটিতে সরাসরি চূড়ান্ত মানটিতে সম্পত্তি আপডেট করা আরও ভাল সমাধান হবে।

self.view.layer.opacity = 1;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = 0;
animation.toValue = 1;
[self.view.layer addAnimation:animation forKey:nil];

উপরের কোডের প্রথম লাইনের ফলে যদি কোনও অন্তর্নিহিত অ্যানিমেশন থাকে তবে তা বন্ধ করার চেষ্টা করুন:

[CATransaction begin];
[CATransaction setDisableActions:YES];
self.view.layer.opacity = 1;
[CATransaction commit];

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = 0;
animation.toValue = 1;
[self.view.layer addAnimation:animation forKey:nil];

ধন্যবাদ! এটি সত্যই গ্রহণযোগ্য উত্তর হওয়া উচিত, কারণ এটি
কার্যকরভাবে

6

এইটা কাজ করে:

let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 0.3

someLayer.opacity = 1 // important, this is the state you want visible after the animation finishes.
someLayer.addAnimation(animation, forKey: "myAnimation")

কোর অ্যানিমেশন অ্যানিমেশন চলাকালীন আপনার স্বাভাবিক স্তরটির উপরে একটি 'উপস্থাপনা স্তর' দেখায়। সুতরাং অ্যানিমেশনটি শেষ হয়ে গেলে এবং উপস্থাপনা স্তরটি চলে গেলে আপনি যা দেখতে চান তাতে অস্বচ্ছতা (বা যাই হোক না কেন) সেট করুন। ফ্লিকারটি সম্পূর্ণ হয়ে গেলে এড়ানোর জন্য অ্যানিমেশনটি যুক্ত করার আগে লাইনে এটি করুন।

আপনি যদি দেরি করতে চান তবে নিম্নলিখিতটি করুন:

let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 0.3
animation.beginTime = someLayer.convertTime(CACurrentMediaTime(), fromLayer: nil) + 1
animation.fillMode = kCAFillModeBackwards // So the opacity is 0 while the animation waits to start.

someLayer.opacity = 1 // <- important, this is the state you want visible after the animation finishes.
someLayer.addAnimation(animation, forKey: "myAnimation")

পরিশেষে, আপনি যদি 'মুছে ফেলা অফকম্পশন = মিথ্যা' ব্যবহার করেন তবে স্তরটি নিষ্পত্তি না হওয়া অবধি এটি সিএএনিমেশনগুলি ফাঁস করবে - এড়িয়ে চলুন।


দুর্দান্ত উত্তর, দুর্দান্ত টিপস। অপসারণ মন্তব্যের জন্য ধন্যবাদ।
iWheelBuy

4

@ লেসলি গডউইনের উত্তরটি সত্যিই ভাল নয়, "সেল্ফ.ভিউ.লেয়ার.ওপ্যাসিটি = 1;" তাত্ক্ষণিকভাবে সম্পন্ন করা হয় (এটি প্রায় এক সেকেন্ড সময় নেয়), যদি আপনার সন্দেহ থাকে তবে দয়া করে alphaAnimation.duration 10.0 এ স্থির করুন। আপনাকে এই লাইনটি সরিয়ে ফেলতে হবে।

সুতরাং, আপনি যখন কেসিএফিলমোডফোরওয়ার্ডে ফিলমোড ঠিক করেন এবং কোনটিতে কমপ্লিট সরিয়ে ফেলেন, আপনি অ্যানিমেশনটি স্তরটিতে থেকে যেতে দিন। আপনি যদি অ্যানিমেশন প্রতিনিধি ঠিক করেন এবং এর মতো কিছু চেষ্টা করেন:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
 [theLayer removeAllAnimations];
}

... আপনি এই লাইনটি কার্যকর করার মুহুর্তে স্তরটি তত্ক্ষণাত পুনরুদ্ধার করে। এটি আমরা এড়াতে চেয়েছিলাম।

এটিকে থেকে অ্যানিমেশনটি সরানোর আগে আপনাকে অবশ্যই স্তর সম্পত্তিটি ঠিক করতে হবে। এটা চেষ্টা কর:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
     if([anim isKindOfClass:[CABasicAnimation class] ]) // check, because of the cast
    {
        CALayer *theLayer = 0;
        if(anim==[_b1 animationForKey:@"opacity"])
            theLayer = _b1; // I have two layers
        else
        if(anim==[_b2 animationForKey:@"opacity"])
            theLayer = _b2;

        if(theLayer)
        {
            CGFloat toValue = [((CABasicAnimation*)anim).toValue floatValue];
            [theLayer setOpacity:toValue];

            [theLayer removeAllAnimations];
        }
    }
}

1

দেখে মনে হচ্ছে মুছে ফেলা অনকম্পশন পতাকাটি মিথ্যাতে সেট হয়েছে এবং ফিলিপড কেসিএফিলমোড ফরওয়ার্ডে সেট করে আমার পক্ষেও কাজ করে না।

আমি একটি স্তরে নতুন অ্যানিমেশন প্রয়োগ করার পরে, একটি অ্যানিমেটিং বস্তু তার প্রাথমিক অবস্থায় পুনরায় সেট করে এবং তারপরে সেই অবস্থা থেকে অ্যানিমেট করে। অতিরিক্তভাবে যা করতে হবে তা হ'ল নতুন অ্যানিমেশন সেট করার আগে মডেল স্তরের পছন্দসই সম্পত্তিটিকে তার উপস্থাপনা স্তরের সম্পত্তি অনুযায়ী সেট করা:

someLayer.path = ((CAShapeLayer *)[someLayer presentationLayer]).path;
[someLayer addAnimation:someAnimation forKey:@"someAnimation"];

0

অন্তর্নিহিত অ্যানিমেশনগুলি ব্যবহার করা সবচেয়ে সহজ সমাধান। এটি আপনার জন্য সমস্ত সমস্যার সমাধান করবে:

self.layer?.backgroundColor = NSColor.red.cgColor;

যদি আপনি যেমন সময়কাল কাস্টমাইজ করতে চান তবে আপনি এটি ব্যবহার করতে পারেন NSAnimationContext:

    NSAnimationContext.beginGrouping();
    NSAnimationContext.current.duration = 0.5;
    self.layer?.backgroundColor = NSColor.red.cgColor;
    NSAnimationContext.endGrouping();

দ্রষ্টব্য: এটি কেবল ম্যাকস-এ পরীক্ষিত।

এটি করার সময় আমি প্রাথমিকভাবে কোনও অ্যানিমেশন দেখিনি। সমস্যাটি হ'ল ভিউ-ব্যাকড লেয়ারের স্তরটি অ্যানিমেটকে অন্তর্ভুক্ত করে না । এটি সমাধান করার জন্য, আপনি নিজেই একটি স্তর যুক্ত করেছেন তা নিশ্চিত করুন (স্তরটিকে ব্যাক-তে-সেট করার আগে)।

এটি কীভাবে করা যায় তার একটি উদাহরণ হ'ল:

override func awakeFromNib() {
    self.layer = CALayer();
    //self.wantsLayer = true;
}

ব্যবহার করে self.wantsLayerআমার পরীক্ষায় কোনও পার্থক্য হয়নি, তবে এর কিছু পার্শ্ব প্রতিক্রিয়া থাকতে পারে যা আমি জানি না।


0

খেলার মাঠের একটি নমুনা এখানে:

import PlaygroundSupport
import UIKit

let resultRotation = CGFloat.pi / 2
let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 300.0))
view.backgroundColor = .red

//--------------------------------------------------------------------------------

let rotate = CABasicAnimation(keyPath: "transform.rotation.z") // 1
rotate.fromValue = CGFloat.pi / 3 // 2
rotate.toValue = resultRotation // 3
rotate.duration = 5.0 // 4
rotate.beginTime = CACurrentMediaTime() + 1.0 // 5
// rotate.isRemovedOnCompletion = false // 6
rotate.fillMode = .backwards // 7

view.layer.add(rotate, forKey: nil) // 8
view.layer.setAffineTransform(CGAffineTransform(rotationAngle: resultRotation)) // 9

//--------------------------------------------------------------------------------

PlaygroundPage.current.liveView = view
  1. একটি অ্যানিমেশন মডেল তৈরি করুন
  2. অ্যানিমেশনের শুরু অবস্থান সেট করুন (এড়িয়ে যেতে পারে, এটি আপনার বর্তমান স্তর বিন্যাসের উপর নির্ভর করে)
  3. অ্যানিমেশনের শেষ অবস্থান সেট করুন
  4. অ্যানিমেশন সময়কাল সেট করুন
  5. এক সেকেন্ডের জন্য বিলম্ব অ্যানিমেশন
  6. সেট করবেন না falseকরার isRemovedOnCompletion- কোর অ্যানিমেশন পরিষ্কার দিন পর অ্যানিমেশন সমাপ্ত হয়
  7. কৌতূহলের প্রথম অংশটি এখানে - আপনি অ্যানিমেশনটি শুরু করার আগে আপনার অ্যানিমেশনটি স্থাপনের জন্য বলছেন (আপনি # 2 ধাপে সেট করেছেন) অ্যানিমেশনটি শুরু হওয়ার আগেই - সময়ের সাথে পিছনে প্রসারিত করুন
  8. প্রস্তুত অ্যানিমেশন অবজেক্টটি অনুলিপি করুন, এটিকে স্তরটিতে যুক্ত করুন এবং বিলম্বের পরে অ্যানিমেশনটি শুরু করুন (আপনি # 5 ধাপে সেট করেছেন)
  9. দ্বিতীয় অংশটি স্তরের সঠিক প্রান্ত অবস্থান নির্ধারণ করা - অ্যানিমেশনটি মোছার পরে আপনার স্তরটি সঠিক জায়গায় প্রদর্শিত হবে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.