ios - CALayer clip CGContextAddArc (making a donut slide/pie chart) -


i'am trying learn , understand coregraphics. i'am trying making pie chart.

the pie chart working fine , looks great, i'am having trouble clipping inner circle.

this code each slide in pie:

cgpoint center = cgpointmake((self.bounds.size.width/2) + self.centeroffset, (self.bounds.size.height/2) - self.centeroffset); cgfloat radius = min(center.x, center.y) - 25; radius *= self.piescale;  cgcontextbeginpath(ctx); cgcontextmovetopoint(ctx, center.x, center.y);  cgpoint p1 = cgpointmake(center.x + radius * cosf(self.startangle), center.y + radius * sinf(self.startangle)); cgcontextaddlinetopoint(ctx, p1.x, p1.y);  int clockwise = self.startangle > self.endangle; cgcontextaddarc(ctx, center.x, center.y, radius, self.startangle, self.endangle, clockwise); cgcontextclosepath(ctx);  cgcontextmovetopoint(ctx, center.x, center.y); cgcontextaddarc(ctx, center.x, center.y, radius*0.5, self.startangle, self.endangle, clockwise);  cgcontextsetfillcolorwithcolor(ctx, self.fillcolor.cgcolor); cgcontextsetstrokecolorwithcolor(ctx, self.strokecolor.cgcolor); cgcontextsetlinewidth(ctx, self.strokewidth);  self.pathref = cgcontextcopypath(ctx); cgcontextdrawpath(ctx, kcgpathfillstroke); 

my current pie looks this:

http://cl.ly/image/1v1d3l3o0u3t

i managed add inner circle drawing new path smaller radius.

i try clip second path cgcontextclip(ctx); leaves me inner circle this:

http://cl.ly/image/2g402n3g3j2g

it kind of makes sense me why happening can't figure else should doing.

edit:

code looks like:

cgpoint center = cgpointmake((self.bounds.size.width/2) + self.centeroffset, (self.bounds.size.height/2) - self.centeroffset); cgfloat radius = min(center.x, center.y) - 25; radius *= self.piescale; cgpoint p1 = cgpointmake(center.x + radius * cosf(self.startangle), center.y + radius * sinf(self.startangle)); int clockwise = self.startangle > self.endangle;  cgcontextbeginpath(ctx); cgcontextmovetopoint(ctx, center.x, center.y);  cgcontextaddlinetopoint(ctx, p1.x, p1.y); cgcontextaddarc(ctx, center.x, center.y, radius, self.startangle, self.endangle, clockwise); cgcontextclosepath(ctx);  cgcontextmovetopoint(ctx, center.x, center.y); cgcontextaddarc(ctx, center.x, center.y, radius*0.5, self.startangle, self.endangle, !clockwise);   cgcontextsetfillcolorwithcolor(ctx, self.fillcolor.cgcolor); cgcontextsetstrokecolorwithcolor(ctx, self.strokecolor.cgcolor); cgcontextsetlinewidth(ctx, self.strokewidth);  self.pathref = cgcontextcopypath(ctx); cgcontextdrawpath(ctx, kcgpathfillstroke); 

looks like:

enter image description here

all drawing code:

my class subclass of calayer. code drawing single slice in pie.

-(void)drawincontext:(cgcontextref)ctx {     cgpoint center = cgpointmake((self.bounds.size.width/2) + self.centeroffset, (self.bounds.size.height/2) - self.centeroffset);     cgfloat radius = min(center.x, center.y) - 25;     radius *= self.piescale;     int clockwise = self.startangle > self.endangle;      /* clipping should done first next path(s) not creating clipping mask */     cgcontextmovetopoint(ctx, center.x, center.y);     cgcontextaddarc(ctx, center.x, center.y, radius*0.5, self.startangle, self.endangle, !clockwise);     //cgcontextclippath(ctx);     cgcontextclip(ctx);      /* now, start drawing graph , filling things in... */     cgcontextbeginpath(ctx);     cgcontextmovetopoint(ctx, center.x, center.y);      cgpoint p1 = cgpointmake(center.x + radius * cosf(self.startangle), center.y + radius * sinf(self.startangle));      cgcontextaddlinetopoint(ctx, p1.x, p1.y);     cgcontextaddarc(ctx, center.x, center.y, radius, self.startangle, self.endangle, clockwise);     cgcontextclosepath(ctx);       cgcontextsetfillcolorwithcolor(ctx, self.fillcolor.cgcolor);     cgcontextsetstrokecolorwithcolor(ctx, self.strokecolor.cgcolor);     cgcontextsetlinewidth(ctx, self.strokewidth);      self.pathref = cgcontextcopypath(ctx);     cgcontextdrawpath(ctx, kcgpathfillstroke);      // labels     uigraphicspushcontext(ctx);     cgcontextsetfillcolorwithcolor(ctx, self.labelcolor.cgcolor);      cgfloat distance = [self angledistance:(self.startangle * 180/m_pi) angle2:(self.endangle * 180/m_pi)];     cgfloat arcdistanceangle = distance * m_pi/180;     cgfloat arccenterangle = self.startangle + arcdistanceangle/2;      cgpoint labelpoint = cgpointmake(center.x + radius * cosf(arccenterangle), center.y + radius * sinf(arccenterangle));       /*      basic drawing of lines labels.. disabled now..     cgcontextbeginpath(ctx);     cgcontextmovetopoint(ctx, labelpoint.x, labelpoint.y);     */      if(labelpoint.x <= center.x)         labelpoint.x -= 50;     else         labelpoint.x += 5;      if(labelpoint.y <= center.y)         labelpoint.y -= 25;        /*       basic drawing of lines labels.. disabled now..     cgcontextaddlinetopoint(ctx, labelpoint.x, labelpoint.y);     cgcontextclosepath(ctx);      cgcontextsetfillcolorwithcolor(ctx, self.fillcolor.cgcolor);     cgcontextsetstrokecolorwithcolor(ctx, self.strokecolor.cgcolor);     cgcontextsetlinewidth(ctx, self.strokewidth);     cgcontextdrawpath(ctx, kcgpathfillstroke);     */      [self.labelstring drawatpoint:labelpoint forwidth:50.0f withfont:[uifont systemfontofsize:18] linebreakmode:nslinebreakbyclipping];     uigraphicspopcontext();  } 

if understand question correctly, want have hole in center , trying use clipping mask that. thing therefore need reverse direction draw inner path tried clip. then, because of fill rules, cut out nice hole you.

your code should this:

cgpoint center = cgpointmake((self.bounds.size.width/2) + self.centeroffset, (self.bounds.size.height/2) - self.centeroffset); cgfloat radius = min(center.x, center.y) - 25; radius *= self.piescale; int clockwise = self.startangle > self.endangle;  /* clipping should done first next path(s) not creating clipping mask */ cgcontextmovetopoint(ctx, center.x, center.y); /* create outer path going clockwise */ cgcontextaddarc(ctx, center.x, center.y, radius*3, 0, 2*m_pi, clockwise); /* create inner path / mask going counter-clockwise make 'hole' in center */ cgcontextaddarc(ctx, center.x, center.y, radius*0.5, 0, 2*m_pi, !clockwise); cgcontextclip(ctx);  /* now, start drawing graph , filling things in... */ cgcontextbeginpath(ctx); /* here's stroke of inner circle */ cgpoint p1 = cgpointmake(center.x + radius/2 * cosf(self.endangle), center.y + radius/2 * sinf(self.endangle)); cgcontextmovetopoint(ctx, p1.x, p1.y); cgcontextaddarc(ctx, center.x, center.y, radius / 2 + 1, self.endangle, self.startangle, !clockwise);  p1 = cgpointmake(center.x + radius * cosf(self.startangle), center.y + radius * sinf(self.startangle));  cgcontextaddlinetopoint(ctx, p1.x, p1.y); cgcontextaddarc(ctx, center.x, center.y, radius, self.startangle, self.endangle, clockwise); cgcontextclosepath(ctx);   cgcontextsetfillcolorwithcolor(ctx, self.fillcolor.cgcolor); cgcontextsetstrokecolorwithcolor(ctx, self.strokecolor.cgcolor); cgcontextsetlinewidth(ctx, self.strokewidth);  self.pathref = cgcontextcopypath(ctx); cgcontextdrawpath(ctx, kcgpathfillstroke); 

update: i've fixed code , run code on github , works. hopefully, fix "hole" problem. (excuse pun)

here's gist of example of technique: https://gist.github.com/rcdilorenzo/6437406


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -