ios - CAAnimation with CALayers occasionally creates flickered animation (video included) -


my app takes still photo , animates mouth region emulate talking. however, 1/4 of time, of hidden calayers flash continuously throughout animation.

here app looks when works properly. here app looks when glitches. edit: better video

i'm assuming issue path related. in app, user creates path around mouth region (shown briefly in video), , animated region. path result in smooth animation, , other times result in glitch above. additionally, if press "back" , try reload controller animation, glitch persists, whereas if change path before reloading, goes away.

if it's not path related, of culprits have eliminated are:

  • image type/source -- work image not image b, , other times work image b not a. i've tried images photo library ones saved internet.

  • iphone vs simulator -- problem occurs on both devices

  • number of pictures animated -- happen on first try; other times happen on 5th or 6th try.

below code view animated. first create layer of black, followed layer picture minus mouth region, , layer of mouth region. shift position of mouth layer, displacement becomes black , looks open mouth.

edit: also, if remove mouth hole removing mask face layer, animation runs smoothly.

- (id)initwithframe:(cgrect)frame leftpt:(cgpoint)point0 rightpt:(cgpoint)point2 vertex1:(cgpoint)vertex1 vertex2:(cgpoint)vertex2 andpicture:(uiimage *)pic{      self = [super initwithframe:frame];     if (self) {          p0 = point0;         p2 = point2;         v1 = vertex1;         v2 = vertex2;         picture = pic;          [self addblacklayer];         [self addfacelayer];         [self addmouthlayer];          self.opaque = yes;     }     return self; } - (void)addblacklayer {      calayer *blacklayer = [calayer layer];     blacklayer.frame = self.bounds;     blacklayer.backgroundcolor = [uicolor blackcolor].cgcolor;     [self.layer addsublayer:blacklayer];  } - (void)addfacelayer {      calayer *facelayer = [calayer layer];     facelayer.frame = self.bounds;     facelayer.contents = (id)[picture cgimagewithproperorientation];     cashapelayer *facemask = [cashapelayer layer];     cgmutablepathref fpath = cgpathcreatemutable();     cgpathmovetopoint(fpath, null, cgrectgetminx(self.bounds), cgrectgetminy(self.bounds));     cgpathaddlinetopoint(fpath, null, cgrectgetmaxx(self.bounds), cgrectgetminy(self.bounds));     cgpathaddlinetopoint(fpath, null, cgrectgetmaxx(self.bounds), cgrectgetmaxy(self.bounds));     cgpathaddlinetopoint(fpath, null, cgrectgetminx(self.bounds), cgrectgetmaxy(self.bounds));     cgpathaddlinetopoint(fpath, null, cgrectgetminx(self.bounds), cgrectgetminy(self.bounds));     cgpathmovetopoint(fpath, null, p0.x, p0.y);     midpt = cgpointmake( (p2.x + p0.x)/2, (p2.y+ p0.y)/2);     cgpoint c1 = cgpointmake(2*v1.x - midpt.x, 2*v1.y - midpt.y); //control points     cgpoint c2 = cgpointmake(2*v2.x - midpt.x, 2*v2.y - midpt.y);      cgpathaddquadcurvetopoint(fpath, null, c1.x, c1.y, p2.x, p2.y);     cgpathaddquadcurvetopoint(fpath, null, c2.x, c2.y, p0.x, p0.y);      facemask.path = fpath;     facelayer.mask = facemask;     [facemask setfillrule:kcafillruleevenodd];     [self.layer addsublayer:facelayer];     cgpathrelease(fpath);  }  - (void)addmouthlayer {      cgmutablepathref mpath = cgpathcreatemutable();     cgpathmovetopoint(mpath, null, p0.x, p0.y);     midpt = cgpointmake( (p2.x + p0.x)/2, (p2.y+ p0.y)/2);     cgpoint c1 = cgpointmake(2*v1.x - midpt.x, 2*v1.y - midpt.y); //control points     cgpoint c2 = cgpointmake(2*v2.x - midpt.x, 2*v2.y - midpt.y);      cgpathaddquadcurvetopoint(mpath, null, c1.x, c1.y, p2.x, p2.y);     cgpathaddquadcurvetopoint(mpath, null, c2.x, c2.y, p0.x, p0.y);      self.mouthlayer = [calayer layer];     cashapelayer *mouthmask = [cashapelayer layer];     self.mouthlayer.frame = self.bounds;     self.mouthlayer.contents = (id)[picture cgimagewithproperorientation];     mouthmask.path = mpath;     mouthmask.frame = mouthlayer.bounds;     self.mouthlayer.mask = mouthmask;     [self.layer addsublayer:mouthlayer];     self.mouthlayer.frame = cgrectmake(mouthlayer.frame.origin.x, mouthlayer.frame.origin.y, mouthlayer.frame.size.width, mouthlayer.frame.size.height);     cgpathrelease(mpath); 

here code creates animation, view controller

- (caanimation *)createanimationwithrepeatcount:(int)count {      cgpoint convertedstartingcenter = [self.view convertpoint:animatedface.center toview:animatedface];     cgpoint endpt = cgpointmake(convertedstartingcenter.x, convertedstartingcenter.y + 15);      cabasicanimation *mouthdown = [cabasicanimation animationwithkeypath:@"position"];     mouthdown.duration = animation_time;     mouthdown.begintime = 0;     mouthdown.fromvalue = [nsvalue valuewithcgpoint:convertedstartingcenter];     mouthdown.tovalue = [nsvalue valuewithcgpoint:endpt];      cabasicanimation *mouthup = [cabasicanimation animationwithkeypath:@"position"];     mouthup.duration = animation_time;     mouthup.begintime = animation_time;     mouthup.fromvalue = [nsvalue valuewithcgpoint:endpt];     mouthup.tovalue = [nsvalue valuewithcgpoint:convertedstartingcenter];      caanimationgroup *totalanimation = [caanimationgroup animation];     [totalanimation setanimations:[nsarray arraywithobjects:mouthdown,mouthup, nil]];     [totalanimation setduration:2*animation_time];     [totalanimation setremovedoncompletion:no];     [totalanimation setfillmode:kcafillmodeforwards];     totalanimation.repeatcount = count;      return totalanimation;  } 

just approach (don't know if tried), use cabasicanimation , set class animation delegate, , in delegate method try start the next cabasicanimation. if didn't tried can provide example you.


Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -