用CAShapeLayer实现一个简单的饼状图(PieView)

自己写了一个简单的PieView,demo在这里: https://github.com/Phelthas/LXMPieView
效果如图:
 
实现方法:
绘制饼状图所需的值只有各个扇形对应的值及对应的颜色,但可能会有很多附加的元素需要显示(比如字体颜色,字体大小等),
所以将每个扇形所需的数据封装为一个model对象,方便以后扩展。
 
1,绘制每个扇形,需要知道扇形的startAngle和endAngle,所以需要计算每个扇形所占的百分比及角度,
然后第一个扇形的start是0,end是第一个扇形的角度,
第二个扇形的start是第一个扇形的end,第二个扇形的end是前两个扇形的角度之和,以此类推
这里写死了饼状图从-0.5*Pi的位置开始绘制,所以计算出每个扇形的startAngle和endAngle,分别保存到数组中。
 
2,绘制各个扇形,
用UIBezierPath的- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise NS_AVAILABLE_IOS(4_0);方法
注意这里这里要用 moveToPoint和 addLineToPoint方法绘制成闭合曲线,方便后面判断。
依次add到self.layer上即可
 
3,添加描述label
这里是计算出每个label应该位于的中心位置,然后把label 直接add到view上。中心位置根据点在圆中的位置用几何方法(忘了的补初中数学)算出来。
 
4,旋转动画
这里还是用layer的mask属性来达到部分渲染的效果,参考我之前的解释: http://www.cnblogs.com/Phelthas/p/4643400.html
 
5,添加点击事件
这里只用了一个tapGesture添加到view上,然后通过gesture的location来判断点中的是哪个区域。
那怎么判断location这个点在不在某个区域内呢???
苹果提供了一个高大上的方法:
/* Return true if `point' is contained in `path'; false otherwise. A point
   is contained in a path if it is inside the painted region when the path
   is filled; if `eoFill' is true, then the even-odd fill rule is used to
   evaluate the painted region of the path, otherwise, the winding-number
   fill rule is used. If `m' is non-NULL, then the point is transformed by
   `m' before determining whether the path contains it. */

CG_EXTERN bool CGPathContainsPoint(CGPathRef __nullable path,
    const CGAffineTransform * __nullable m, CGPoint point, bool eoFill)
    CG_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
 
例:
    CGPoint location = [sender locationInView:sender.view];
    CGAffineTransform transform = CGAffineTransformIdentity;   
    NSInteger index = -1;
    for (int i = 0; i < self.subLayerArray.count; i ++) {
        CAShapeLayer *shapeLayer = self.subLayerArray[i];
        if (CGPathContainsPoint(shapeLayer.path, &transform, location, 0)) {
            index = i;
            break;
        }
    }
 
6,用delegate的方式将点击事件回调出去
这个只是为了方便外部调用而进行的封装,同时也是为了逻辑分离,代码整洁~~

转载于:https://www.cnblogs.com/Phelthas/p/4892854.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在iOS中使用CAShapeLayer进行绘图是一种非常方便和高效的方法。CAShapeLayer一个类似于CALayer的图层,它可以用来绘制矢量图形。使用CAShapeLayer可以避免使用Core Graphics绘图时可能遇到的一些性能问题。 下面是一个简单的例子,演示如何使用CAShapeLayer绘制一个圆形: 1. 创建CAShapeLayer对象 ``` CAShapeLayer *circleLayer = [CAShapeLayer layer]; ``` 2. 设置CAShapeLayer的属性 ``` // 设置填充颜色 circleLayer.fillColor = [UIColor clearColor].CGColor; // 设置描边颜色 circleLayer.strokeColor = [UIColor redColor].CGColor; // 设置描边宽度 circleLayer.lineWidth = 5; // 设置路径 CGFloat radius = 50; circleLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius*2, radius*2)].CGPath; // 设置位置 circleLayer.position = CGPointMake(100, 100); ``` 3. 将CAShapeLayer添加到视图中 ``` [self.view.layer addSublayer:circleLayer]; ``` 这样,一个圆形就被绘制出来了。 除了绘制基本图形,还可以通过CAShapeLayer绘制复杂的路径,例如: ``` CAShapeLayer *pathLayer = [CAShapeLayer layer]; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(100, 100)]; [path addLineToPoint:CGPointMake(200, 200)]; [path addLineToPoint:CGPointMake(100, 300)]; [path addLineToPoint:CGPointMake(0, 200)]; [path closePath]; pathLayer.path = path.CGPath; pathLayer.strokeColor = [UIColor redColor].CGColor; pathLayer.fillColor = [UIColor clearColor].CGColor; pathLayer.lineWidth = 5; [self.view.layer addSublayer:pathLayer]; ``` 这个例子中,我们使用UIBezierPath创建了一个具有四个顶点的路径,并将其添加到CAShapeLayer中,然后将CAShapeLayer添加到视图中。 使用CAShapeLayer进行绘图非常方便和高效。希望这篇回答对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值