ios - CABasicAnimation does not animate correctly when I update model layer -


i'm implementing cabasicanimation animates calayer transform property. now, although i'm new core animation, have been able gather through various blogs , articles such objc.io bad idea use (incorrectly) recommended method getting animations stick using fillmode , removedoncompletion properties of animation. method considered bad practice many because creates discrepancy between model layer , presentation layer, , future queries 1 of layers may not match user seeing.

instead, recommended way of doing animations update model layer @ same time add animation layer being animated. however, i'm having trouble understanding how working. animation simple, , goes this:

catransform3d updatedtransform = [self newtransformwithcurrenttransform]; // location 1 cabasicanimation *transformanimation = [cabasicanimation animationwithkeypath:@"transform"]; transformanimation.duration = 1; transformanimation.fromvalue = [nsvalue valuewithcatransform3d:self.layerbeinganimated.transform]; // not work without this. transformanimation.tovalue = [nsvalue valuewithcatransform3d:updatedtransform]; // location 2 [self.layerbeinganimated addanimation:transformanimation forkey:ktransformanimationkey]; // location 3 

i've denoted 3 locations have attempted update model layer using code

self.layerbeinganimated.transform = updatedtransform; 

in location 1, layer jumps right newtransform , not animate. in location 2, layer animates want current transform newtransform. in location 3, layer jumps right newtransform, jumps the old transform, animates correctly fromvalue newtransform, , stays @ newtransform.

what's deal here? what's correct location update model layer , why these 3 locations producing such different results?

thanks!

i think it's easiest explain happening each of 3 locations , "conclusion" @ end.

i'm adding illustrations, showing behaviour mentioning in question easier follow hasn't tried these 3 things themselves. i'm extending illustration show both stand alone layer , backing layer (one attached view) , explain difference there one.

location 1

in first location, model value updated before animation created. once done, transform property holds updatedtransform. means when read transform layer fromvalue, updatedvalue back. in turn means both , value same can't see animation.

enter image description here

one thing have made location work expected read oldvalue before assigning new value , use fromvalue. expected.

// location 1 catransform3d oldvalue = layer.transform; // read old value first layer.transform = updatedtransform;       // update new value  cabasicanimation *anim = [cabasicanimation animationwithkeypath:@"transform"]; anim.duration  = 1.0; anim.fromvalue = [nsvalue valuewithcatransform3d:oldvalue]; anim.tovalue   = [nsvalue valuewithcatransform3d:updatedtransform]; 

location 2

in second example, value isn't yet updated when read transform value, fromvalue , tovalue different. after that, model value updated it's final value. there difference between stand-alone layer , backing layer here, don't see it. transform property on calayer animatable , automatically perform "implicit" animation when value changes. means animation added layer "transform" key path. view, however, disables behaviour when change happens outside of animation block, there not implicit animation there.

the reason why don't see implicit animation "explicit" animation added afterwards same key path. means explicit animation visible, in both cases, thought there 2 animation running on stand-alone layer (more on later). if feeling cautious, disable implicit action stand-alone layer (more on later).

enter image description here

location 3

this leaves last location. in case animation created above, different fromvalue , tovalue. difference order of adding explicit animation , changing property triggers implicit animation. in case implicit animation added after explicit animation , both run(!). both animations ran location 2, couldn't see because explicit (longer) animation added after.

enter image description here

since moving fast, slowed down entire layer try , illustrate happening when 2 animations running @ once. way becomes easier see happens when implicit animation ends. i've overlaid behaving backing layer , misbehaving stand-alone layer , made them both 50% transparent. dashed outline original frame.

enter image description here

a short description of happening: blue view get's explicit animation added (which has 1 second duration). orange layer first has same exploit animation added , has implicit 0.25 second animation added it. neither explicit nor implicit animations "additive", meaning tovalue , fromvalue used as-is.

disclaimer: not work @ apple , haven't seen source code core animation i'm guesswork based on how things behave.

in understanding (see disclaimer) happens every screen refresh produce animation: current time stamp, layer goes through animations in order added , updates presentation values. in case, explicit animation sets rotation transform, implicit animation comes , sets rotation transform overrides explicit transform.

if animation configured "additive", add presentation values instead of overwriting (which super powerful). additive animations, order still matters. non-additive animation come later , overwrite whole thing.

since implicit animation shorter explicit one, see first part of total animation, values strictly coming implicit animation (which added last). once implicit animation finishes, remaining animation explicit animation has been running underneath implicit one, time. when implicit animation finishes, explicit animation has progressed 0.25 seconds , see orange layer jumps same value blue view, instead of jumping beginning.

where should update value?

at point, question is, how can prevent 2 animations being added , should update value? location value updated doesn't prevent there being 2 animations (but can affect how end result looks).

to prevent 2 actions being added stand-alone layer, temporarily disable "actions" (a more general term animation):

[catransaction begin]; [catransaction setdisableactions:yes]; // actions disabled layer.transform = updatedtransform; [catransaction commit];                // until here 

when this, 1 animation added layer either location 2 or 3 works. matter of taste. if read oldvalue, can use location 1 (as long action disabled).

if animating backing layer don't have disable actions (the view you) doesn't hurt so.


at point keep going other ways configure animation, additive animation is, , why needed specify both tovalue , fromvalue in case. think have answered question asked , answer bit on long side.


Comments

Popular posts from this blog

c++ - OpenCV Error: Assertion failed <scn == 3 ::scn == 4> in unknown function, -

php - render data via PDO::FETCH_FUNC vs loop -

The canvas has been tainted by cross-origin data in chrome only -