以编程方式绘制iOS 7风格的圆形

我试图find一种方法来使用核心graphics以编程方式绘制iOS 7样式图标“squircle”形状。 我不问如何绘制一个圆angular的矩形 。 一个圆形是一个超椭圆:

方圆形

与常规的圆angular矩形略有不同: 圆角矩形与圆形

在圆形的音乐图标

这是确切的公式是容易获得的 。 然而,我不知道如何使用,例如,一个CGPath,更不用说填充它,并能够相当容易地调整它。 所有这一切与公式完全一致。 任何想法?

从维基百科引用: Superellipse

特别地,对于n = 1/2,四个弧中的每一个都是由两个轴定义的二次Bézier曲线 ; 结果,每个弧是抛物线的一部分。

那么为什么不尝试使用贝塞尔曲线近似Squircle? 两条曲线(Bezier和Squircle)由参数方程定义。

UIBezierPath类有方法: addCurveToPoint:controlPoint1:controlPoint2: controlPoint1 : addCurveToPoint:controlPoint1:controlPoint2:

在接收器的path上添加一个三次贝塞尔曲线。

注意:使用addQuadCurveToPoint:controlPoint:方法给出了更差的结果 – testing。

我使用这种方法,结果如下:

red line – 圆angular矩形, blue line – 四条Bezier曲线的矩形

圆角矩形与三次贝塞尔曲线

如果这个结果是有兴趣的 – 下面的代码。

注意:要实现更精确的匹配,可以要求改变corner points的坐标(现在它们对应于其中刻有图的矩形的angular度)。

 CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSaveGState(context); //set rect size for draw float rectSize = 275.; CGRect rectangle = CGRectMake(CGRectGetMidX(rect) - rectSize/2, CGRectGetMidY(rect) - rectSize/2, rectSize, rectSize); //Rounded rectangle CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); UIBezierPath* roundedPath = [UIBezierPath bezierPathWithRoundedRect:rectangle cornerRadius:rectSize/4.7]; [roundedPath stroke]; //Rectangle from Fours Bezier Curves CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); UIBezierPath *bezierCurvePath = [UIBezierPath bezierPath]; //set coner points CGPoint topLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMinY(rectangle)); CGPoint topRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMinY(rectangle)); CGPoint botLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMaxY(rectangle)); CGPoint botRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMaxY(rectangle)); //set start-end points CGPoint midRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMidY(rectangle)); CGPoint botMPoint = CGPointMake(CGRectGetMidX(rectangle), CGRectGetMaxY(rectangle)); CGPoint topMPoint = CGPointMake(CGRectGetMidX(rectangle), CGRectGetMinY(rectangle)); CGPoint midLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMidY(rectangle)); //Four Bezier Curve [bezierCurvePath moveToPoint:midLPoint]; [bezierCurvePath addCurveToPoint:topMPoint controlPoint1:topLPoint controlPoint2:topLPoint]; [bezierCurvePath moveToPoint:midLPoint]; [bezierCurvePath addCurveToPoint:botMPoint controlPoint1:botLPoint controlPoint2:botLPoint]; [bezierCurvePath moveToPoint:midRPoint]; [bezierCurvePath addCurveToPoint:topMPoint controlPoint1:topRPoint controlPoint2:topRPoint]; [bezierCurvePath moveToPoint:midRPoint]; [bezierCurvePath addCurveToPoint:botMPoint controlPoint1:botRPoint controlPoint2:botRPoint]; [bezierCurvePath stroke]; CGContextRestoreGState(context); 

这不是一个很好的答案,因为它没有达到你要求的核心,即如何以编程方式绘制一个超椭圆**,但你可以:

  1. 下载SVG的iOS7图标形状: http ://dribbble.com/shots/1127699-iOS-7-icon-shape-PSD
  2. 将其导入到您的Xcode项目
  3. 将PocketSVG添加到您的项目中: https : //github.com/arielelkin/PocketSVG
  4. 加载SVG,并将其转换为UIBezierPath,从那里你可以缩放和转换你喜欢的:

     PocketSVG *myVectorDrawing = [[PocketSVG alloc] initFromSVGFileNamed:@"iOS_7_icon_shape"]; UIBezierPath *myBezierPath = myVectorDrawing.bezier; // Apply your transforms here: [myBezierPath applyTransform:CGAffineTransformMakeScale(2.5, 2.5)]; [myBezierPath applyTransform:CGAffineTransformMakeTranslation(10, 50)]; CAShapeLayer *myShapeLayer = [CAShapeLayer layer]; myShapeLayer.path = myBezierPath.CGPath; myShapeLayer.strokeColor = [[UIColor redColor] CGColor]; myShapeLayer.lineWidth = 2; myShapeLayer.fillColor = [[UIColor clearColor] CGColor]; [self.view.layer addSublayer:myShapeLayer]; 

**也许值得注意的是,形状可能不是一个精确的超椭圆形: http ://i.imgur.com/l0ljVRo.png

这在使用着色器的OpenGL ES中很容易实现。 只需绘制一个四边形,并将x和y作为顶点属性。 在片段着色器中,将x和y插入等式中。 如果结果<= 1,那么片段在形状内。 如果我可以有空闲的时间,我可以试试这个,并把它张贴在这里。

如果你想使用CGPath,我认为关键是参数化x和y的t,从0到2π。 然后定期评估x和y。 我也会在空闲时间试图弄明白这一点,但是我的math有点生疏。

顺便说一句,我敢肯定,苹果是使用这个公式。 查看@millimoose发布的链接: http ://blog.mikeswanson.com/post/62341902567/unleashing-genetic-algorithms-on-the-ios-7-icon