ios - animate a UIView using CADisplayLink 'combined' with CAMediaTimingFunction. (to get a arbitrary curve) -
i using cadisplaylink
view animation interpolates value , redraws view itself.
e.g. have view myview
, has property value
, whenever value set call setneedsdisplay
, view knows draw.
to animate use cadisplaylink
, want view 'morph' between values. interpolating value animation's start , stop value:
- (cgfloat)interpolatedvalue:(cgfloat)sourcevalue withvalue:(cgfloat)targetvalue forprogress:(cgfloat)progress;
now getting linear progress easy , getting 'specific curve' (ok) want able take advantage of camediatimingfunction
(or other preexisting logic - don't want reinvent wheel again' :)
there's awesome gist rstiming
might handy in case. can define timing functions either using standard camediatimingfunction or define custom ones using 2 control points define bezier curve.
if got setup, may have this:
viewcontroller
#import "viewcontroller.h" #import "animatedview.h" #include <stdlib.h> @interface viewcontroller () @property (nonatomic, strong) cadisplaylink *displaylink; @property (weak, nonatomic) iboutlet animatedview *viewtoanimate; @end @implementation viewcontroller - (void)viewdidload { [super viewdidload]; self.displaylink = [cadisplaylink displaylinkwithtarget:self selector:@selector(updateframe)]; [self.displaylink addtorunloop:[nsrunloop currentrunloop] formode:nsdefaultrunloopmode]; } - (void)updateframe { [self.viewtoanimate updateanimation]; } - (ibaction)updateanimationtapped:(id)sender { self.viewtoanimate.value = arc4random_uniform(101) / 100.0; nslog(@"next animation value: %f", self.viewtoanimate.value); } @end
animatedview
#import "animatedview.h" #import "rstimingfunction.h" @interface animatedview() { cgfloat _lastvalue; cgfloat _progressstep; cgfloat _currentprogress; } @property (nonatomic, strong) rstimingfunction *animationprogress; @end @implementation animatedview - (instancetype)initwithcoder:(nscoder *)adecoder { if ((self = [super initwithcoder:adecoder])) { _progressstep = 0.01; // defines animation speed _currentprogress = 1.0; self.animationprogress = [rstimingfunction timingfunctionwithname:krstimingfunctioneaseineaseout]; } return self; } - (void)setvalue:(cgfloat)value { if (_value != value) { _lastvalue = _value; _value = value; _currentprogress = 0.0; } } - (void)updateanimation { if (_currentprogress > 1.0) return; _currentprogress += _progressstep; cgfloat currentanimationvalue = _lastvalue + (_value - _lastvalue) * [self.animationprogress valueforx:_currentprogress]; self.alpha = currentanimationvalue; // example animate alpha } @end
as said can set 2 control points create timing function modelled on cubic bezier curve.
self.animationprogress = [rstimingfunction timingfunctionwithcontrolpoint1:cgpointmake(0.6, 0.6) controlpoint2:cgpointmake(0.1, 0.8)];
which produce following timing animation (produced using camediatimingfunction playground)
Comments
Post a Comment