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
Post a Comment