以编程方式绘制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);
这不是一个很好的答案,因为它没有达到你要求的核心,即如何以编程方式绘制一个超椭圆**,但你可以:
- 下载SVG的iOS7图标形状: http ://dribbble.com/shots/1127699-iOS-7-icon-shape-PSD
- 将其导入到您的Xcode项目
- 将PocketSVG添加到您的项目中: https : //github.com/arielelkin/PocketSVG
-
加载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