ios - UIBezierPath & CAShapeLayer initial animation jump -


i built company: https://github.com/busycm/bzystroketimer , during course of building, noticed interesting "bug" can't seem mitigate when using uibezierpath. right when animation starts, path jumps number of pixels forward (or backwards depending if it's counterclockwise) instead of starting smooth, incremental animation. , found that's interesting how path jumps forward value of line width cashaperlayer.

so example, if bezier path starts off @ cgrectgetmidx(self.bounds) , line 35, animation starts cgrectgetmidx(self.bounds)+35 , larger line width, more noticeable jump is. there way rid of path smoothly animate out start point?

here's picture of first frame. looks after animation starts. enter image description here

then when resume animation , pause again, distance moved 1/100th of distance see in picture.

here's bezier path code:

- (uibezierpath *)generatepathwithxinset:(cgfloat)dx withyinset:(cgfloat)dy clockwise:(bool)clockwise{     uibezierpath *path = [uibezierpath bezierpath];     [path movetopoint:cgpointmake(cgrectgetmidx(self.bounds)+dx/2, dy/2)];     [path addlinetopoint:cgpointmake(cgrectgetmaxx(self.bounds)-dx/2, dy/2)];     [path addlinetopoint:cgpointmake(cgrectgetmaxx(self.bounds)-dx/2, cgrectgetmaxy(self.bounds)-dy/2)];     [path addlinetopoint:cgpointmake(dx/2, cgrectgetmaxy(self.bounds)-dy/2)];     [path addlinetopoint:cgpointmake(dx/2, dy/2)];     [path closepath];     return clockwise ? path : [path bezierpathbyreversingpath]; } 

here's animation code:

cabasicanimation *wind = [self generateanimationwithduration:self.duration == 0 ? kdefaultduration : self.duration fromvalue:@(self.shapelayer.strokestart) tovalue:@(self.shapelayer.strokeend) withkeypath:keypath withfillmode:kcafillmodeforwards]; wind.timingfunction = [camediatimingfunction functionwithname:self.timingfunction]; wind.removedoncompletion = no; self.shapelayer.path = [self generatepathwithxinset:self.linewidth withyinset:self.linewidth clockwise:self.clockwise].cgpath; [self.shapelayer addanimation:wind forkey:@"strokeendanimation"]; 

and here's how construct cashapelayer.

- (cashapelayer *)shapelayer {     return !_shapelayer ? _shapelayer = ({         cashapelayer *layer = [cashapelayer layer];         layer.linewidth = kdefaultlinewidth;         layer.fillcolor = uicolor.clearcolor.cgcolor;         layer.strokecolor = [uicolor blackcolor].cgcolor;         layer.linecap = kcalinecapsquare;         layer.frame = self.bounds;         layer.strokestart = 0;         layer.strokeend = 1;         layer;     }) : _shapelayer; }    

i think what's happening here that, in frame of animation, drawing line consists of single point. since line has thickness associated it, , line cap type kcalinecapsquare, that'll rendered square height , width equal line width.

you can think of if drawing line square marker, , going drag midpoint of marker goes through every point in curve specified. first point in line, it's if marker touches down @ point, leaving square behind.

here's visual representation different line cap types make more intuitive. should change line cap style kcalinecapbutt.

sidenote: after make change, in line of code

[path movetopoint:cgpointmake(cgrectgetmidx(self.bounds)+dx/2, dy/2)];

you don't have offset x coordinate dx/2 anymore.


Comments

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -