Cum pot realiza rotația continuă a unui NSImage în cadrul NSImageView?

VIITORI VIZATORI:

I have managed to finish this rotation animation and code with description can be found on tho question. NSImage rotation in NSView is not working

Înainte de a continua, răspundeți la răspunsul lui Duncan C . Pe măsură ce reușesc să obțin această rotație din răspunsul său.


Am o imagine ca asta,

enter image description here

Vreau să mențină rotirea acestei pictograme de sincronizare, pe un fir diferit. Acum am încercat să folosesc compozitorul Quartz și să adaug animația la QCView, dar are un efect foarte nebun și foarte lent.

Întrebare:

Cum pot roti această imagine în mod continuu cu cheltuieli de procesare foarte mici?

Efort

Am citit documentația CoreAnimation, Quartz2D, dar nu am reușit să găsesc calea pentru ao face să funcționeze. Singurul lucru pe care îl știu până acum este că trebuie să-l folosesc

  • CALayer
  • CAImageRef
  • AffineTransform
  • NSAnimationContext

Acum, nu astept codul, dar o intelegere cu codul pseudo va fi grozava!

9

2 răspunsuri

Obținerea unui obiect care să se rotească la mai mult de 180 de grade este de fapt un pic dificil. Problema este că specificați o matrice de transformare pentru rotația finală, iar sistemul decide să se rotească în cealaltă direcție.

Ceea ce am făcut este să creez o CABasicAnimație de mai puțin de 180 de grade, setată a fi aditivă și cu un număr repetat. Fiecare pas din animație animă obiectul mai mult.

Următorul cod este preluat dintr-o aplicație iOS, dar tehnica este identică în Mac OS.

  CABasicAnimation* rotate =  [CABasicAnimation animationWithKeyPath: @"transform.rotation.z"];
  rotate.removedOnCompletion = FALSE;
  rotate.fillMode = kCAFillModeForwards;

  //Do a series of 5 quarter turns for a total of a 1.25 turns
  //(2PI is a full turn, so pi/2 is a quarter turn)
  [rotate setToValue: [NSNumber numberWithFloat: -M_PI/2]];
  rotate.repeatCount = 11;

  rotate.duration = duration/2;
  rotate.beginTime = start;
  rotate.cumulative = TRUE;
  rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

Obiectele CAAnimation funcționează pe straturi, deci pentru Mac OS, va trebui să setați proprietatea "wants layer" în constructorul de interfață și apoi să adăugați animația în stratul vizual al dvs.

Pentru ca vederea să se rotească pentru totdeauna, ați seta numărătoarea repetată la un număr foarte mare, cum ar fi 1e100.

Odată ce v-ați creat animația, ați adăuga-o în stratul vizual al dvs. cu un cod similar:

[myView.layer addAnimation: rotate forKey: @"rotateAnimation"];

Este vorba despre tot ce există.

15
adăugat

Actualizați:

Am aflat de curând un alt mod de a gestiona rotații mai mari de 180 de grade sau rotații continue.

Există un obiect special numit CAValueFunction care vă permite să aplicați o modificare a transformării stratului dvs. utilizând o valoare arbitrară, inclusiv valori care specifică mai multe rotații complete.

Creați o CABasicAnimație a proprietății de transformare a stratului dvs., dar în loc de a furniza o transformare, valoarea pe care o furnizați este un NSNumber care oferă noul unghi de rotație. Dacă oferiți un nou unghi ca 20pi, stratul dvs. va roti 10 rotații complete (2pi/rotație). Codul arată astfel:

//Create a CABasicAnimation object to manage our rotation.
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform"];

rotation.duration = 10.0;
CGFLOAT angle = 20*M_PI;

//Set the ending value of the rotation to the new angle.
rotation.toValue = @(angle);

//Have the rotation use linear timing.
rotation.timingFunction = 
  [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

/*
 This is the magic bit. We add a CAValueFunction that tells the CAAnimation we are 
 modifying the transform's rotation around the Z axis.
 Without this, we would supply a transform as the fromValue and toValue, and 
 for rotations > a half-turn, we could not control the rotation direction.

 By using a value function, we can specify arbitrary rotation amounts and 
 directions and even rotations greater than 360 degrees.
*/

rotation.valueFunction = 
  [CAValueFunction functionWithName: kCAValueFunctionRotateZ];



/*
 Set the layer's transform to it's final state before submitting the animation, so 
 it is in it's final state once the animation completes.
*/
imageViewToAnimate.layer.transform = 
  CATransform3DRotate(imageViewToAnimate.layer.transform, angle, 0, 0, 1.0);

[imageViewToAnimate.layer addAnimation:rotation forKey:@"transform.rotation.z"];

(Am extras codul de mai sus dintr-o aplicație de exemplificare și am scos câteva lucruri care nu au fost direct legate de subiect. Puteți vedea acest cod în uz în proiectul

2
adăugat
@ robertmiles3 Cred că are de a face cu punctul de ancoră a oricărui lucru pe care încerci să-l animi. Utilizați [myView.layer setAnchorPoint: CGPointMake (0.5, 0.5)]
adăugat autor CoderNinja, sursa
Aveți probleme cu rotirea în jurul valorii de 0,0 (partea stângă în partea de jos) în loc de centru? Mă înnebunesc și indiferent de ceea ce fac cu punctul de ancorare și cu poziția stratului, nu pot să-l găsesc în centru.
adăugat autor robertmiles3, sursa