您的位置:首页 > 产品设计 > UI/UE

iOS绘图CALayer、UIBezierPath运用(边框、填充、复制、渐变)

2017-10-12 14:18 344 查看
一.动态折线图效果图



1.首先绘制网格和坐标CAReplicatorLayer
   //添加网格图层
   //网格列线
   CAReplicatorLayer
*rowReplicatorLayer = [CAReplicatorLayernew];
   _xReplicatorLayer
= rowReplicatorLayer;
    rowReplicatorLayer.position=

CGPointMake(0,0);
   CALayer
*rowBackLine = [CALayernew];
   _xBackLine
= rowBackLine;
    [rowReplicatorLayeraddSublayer:rowBackLine];
    [mainView.layeraddSublayer:rowReplicatorLayer];
   //网格横线
   CAReplicatorLayer
*columnReplicatorLayer = [CAReplicatorLayernew];
   _yReplicatorLayer
= columnReplicatorLayer;
    columnReplicatorLayer.position=

CGPointMake(0,0);
   CALayer
*columnBackLine = [CALayernew];
   _yBackLine
= columnBackLine;
    [columnReplicatorLayeraddSublayer:columnBackLine];
    [mainView.layeraddSublayer:columnReplicatorLayer];

    //图层绘制动画
    [CATransactionbegin];
    [CATransactionsetAnimationDuration:0];
   CGFloat
rowSpacing =

_heightGrid;
   CGFloat
columnSpacing =

_widthGrid;
   //坐标轴这里我简单的使用label循环创建
   _XLabelView.frame=

CGRectMake(_YLabelWidth-_widthGrid/2,_mainView.frame.size.height-_XLabelHeight,_mainView.frame.size.width-_YLabelWidth,_XLabelHeight);
   _YLabelView.frame=

CGRectMake(0,0-_heightGrid/2+_YunitLabelHeight,_YLabelWidth,_mainView.frame.size.height-_XLabelHeight);
   //图层复制(设置复制的数量)
   _xReplicatorLayer.instanceCount=

_numberY+1;
   _yReplicatorLayer.instanceCount=

_valueData.count;
   
   _xReplicatorLayer.instanceTransform=

CATransform3DMakeTranslation(0,
rowSpacing +
_widthLine,0);
   _yReplicatorLayer.instanceTransform=

CATransform3DMakeTranslation(columnSpacing +_widthLine,0,0);
   //设置图层大小
   _yReplicatorLayer.frame=

_xReplicatorLayer.frame=

CGRectMake(_YLabelWidth,_YunitLabelHeight,_mainView.frame.size.width-_YLabelWidth-_spaceWidth,_mainView.frame.size.height-_XLabelHeight-_YunitLabelHeight);
   
   _yBackLine.frame=

CGRectMake(0,0,_widthLine,_yReplicatorLayer.frame.size.height);
   _xBackLine.frame=

CGRectMake(0,0,_yReplicatorLayer.frame.size.width,_widthLine);
[CATransactioncommit];

2.绘制曲线和折点
   //曲线
   _curveLineLayer.strokeColor=

_curveLineColor.CGColor;
   _curveLineLayer.lineWidth=

_curveLineWidth;

   CAShapeLayer
*curveLineLayer = [CAShapeLayernew];
   _curveLineLayer
= curveLineLayer;
    curveLineLayer.fillColor=

nil;
    curveLineLayer.lineJoin=

kCALineJoinRound;
    [mainView.layeraddSublayer:curveLineLayer];
/**
 将数值转换成坐标
 */
-(CGPoint)_changeValueToPoint:(NSDictionary*)data{
   CGFloat
xValue = [data[JHChartViewX]floatValue];
   CGFloat
yValue = [data[JHChartViewY]floatValue];
   //x坐标等于value*宽度
   //y坐标等于value/最大值*y高度
   CGPoint
point =

CGPointMake(_YLabelWidth+
xValue *(_widthGrid+

_widthLine),_YunitLabelHeight+(1-yValue/_maxY)*_yBackLine.frame.size.height);
   return
point;
   
}
/**
 生成坐标点
 */
-(void)_creatPoint{
   _pointData
=
@[].mutableCopy;
   for
(NSDictionary*dict

in
_valueData) {
//转换成当前坐标点
       CGPoint
point = [self_changeValueToPoint:dict];
        [_pointDataaddObject:[NSValuevalueWithCGPoint:point]];
    }
   CGFloat
sum =
0;
   //计算总长度
   for
(inti =

0; i<_pointData.count-1;
i++) {
     CGPoint
p1 = [_pointData[i]CGPointValue];
     CGPoint
p2 = [_pointData[i+1]CGPointValue];
       CGFloat
temp =

sqrt(pow((p1.x-p2.x),2)+pow((p1.y-p2.y),2));
        sum += temp;
    }
   _sumLineWidth
= sum;
}
/**
 生成路径
 */
-(void)_creatPath{
 
    [self_creatPoint];
   UIBezierPath
* path = [UIBezierPathbezierPath];
   UIBezierPath
*backPath = [UIBezierPathbezierPath];
   CGPoint
firstPoint = [_pointData[0]CGPointValue];
   CGPoint
lastPoint = [_pointData[_pointData.count-

1]CGPointValue];
    [pathmoveToPoint:firstPoint];
    [backPathmoveToPoint:CGPointMake(firstPoint.x,_yBackLine.frame.size.height+_YunitLabelHeight)];
   for
(NSValue*pointValuein

_pointData) {
       CGPoint
point = [pointValue

CGPointValue];
       if
(pointValue ==_pointData[0])
{
            [backPathaddLineToPoint:point];
           continue;
        }
        [backPathaddLineToPoint:point];
        [pathaddLineToPoint:point];
    }
    [backPathaddLineToPoint:CGPointMake(lastPoint.x,_yBackLine.frame.size.height+_YunitLabelHeight)];
   _path
= path;
//背景路径
   _backPath
= backPath;
   
}
/**
 绘制坐标点
 
 @param point坐标点
 @param index标记tag
 */
- (void)drawPoint:(CGPoint)point
withIndex:(NSInteger)index{
}

3.绘制背景
//封闭阴影
   CAShapeLayer
* backLayer = [CAShapeLayernew];
   _backLayer
= backLayer;
    [mainView.layeraddSublayer:backLayer];
   
   CAShapeLayer
*progressLayer = [CAShapeLayerlayer];
   _progressLayer
= progressLayer;
    [_backLayersetMask:progressLayer];
   //背景
   _backLayer.fillColor=

_fillLayerBackgroundColor.CGColor;
   _backLayer.hidden=

_fillLayerHidden;
   //背景路劲
   _backLayer.path=

_backPath.CGPath;
//背景移动遮罩
   CGFloat
lineWidth =

_yReplicatorLayer.frame.size.height+_YunitLabelHeight;
   _progressLayer.lineWidth=
lineWidth*2;
   _progressLayer.lineCap=

kCALineCapSquare;
   _progressLayer.strokeColor=
[UIColorwhiteColor].CGColor;
   //将路径填充颜色设置为透明
   _progressLayer.fillColor=
[UIColorredColor].CGColor;
4.添加动画效果
    4.1曲线绘制动画
CABasicAnimation*pointAnim = [CABasicAnimationanimationWithKeyPath:@"strokeEnd"];
        pointAnim.fromValue=

@0.0;
        pointAnim.toValue=

@1.0;
        pointAnim.duration=

_drawAnimationDuration;
        [_curveLineLayeraddAnimation:pointAnimforKey:@"drawLine”];

#warning 背景是默认全部填充的,无法像曲线一样移动,故采用setMask:方法,给它加上一个遮罩。利用遮罩的绘制动画,模拟出背景的动画
 //图层直线的轨迹
       UIBezierPath
*path = [UIBezierPathbezierPath];
#warning起始点似乎有问题
        [pathmoveToPoint:CGPointMake(-_widthGrid*2,0)];
        [pathaddLineToPoint:CGPointMake(_yReplicatorLayer.frame.size.width,0)];
       _progressLayer.path=
path.CGPath;
       _progressLayer.strokeEnd=

0.0;
       //动画时间
       CGFloat
duration =

_drawAnimationDuration*(_sumLineWidth/_yReplicatorLayer.frame.size.width);
       //进度程度
       CGFloat
progress =

1.0;
       //strokeEnd

动画到某个点结束
       CABasicAnimation
*animate = [CABasicAnimationanimationWithKeyPath:@"strokeEnd"];
        animate.removedOnCompletion=

NO;
        animate.fillMode=

kCAFillModeForwards;
        animate.duration=
duration;
        animate.fromValue=

@0.0;
        animate.toValue=

@(progress);
       //为图层添加动画
        [_progressLayeraddAnimation:animateforKey:@"drawProgress”];
二.动态渐变色百分比移动图效果图
效果图



1.绘制渐变色曲线CAGradientLayer
//将渐变图层添加到animationView的图层上
    [self.animationView.layeraddSublayer:self.gradientLayer];
    [self.gradientLayeraddSublayer:self.gradientColorLayer];
_gradientLayer= [CALayerlayer];
_gradientColorLayer= [CAGradientLayerlayer];
 _gradientLayer.frame=

CGRectMake(0,0,_animationView.frame.size.width,_animationView.frame.size.height);
   _gradientColorLayer.frame=

CGRectMake(0,0,_animationView.frame.size.width,_animationView.frame.size.height);
   _gradientColorLayer.cornerRadius=

_gradientLayer.frame.size.height/2;
        [_gradientColorLayersetColors:[NSArrayarrayWithObjects:(id)_startColor.CGColor,(id)_endColor.CGColor,nil]];
       //渐变方向水平
        [_gradientColorLayersetStartPoint:CGPointMake(0,1)];
2.添加蒙版CAShapeLayer
CGFloatlineWidth =progressHeight;
       
       _progressLayer
= [CAShapeLayerlayer];
       
       _progressLayer.lineWidth=
lineWidth*2;
       _progressLayer.lineCap=

kCALineCapSquare;
       _progressLayer.strokeColor=
[UIColorwhiteColor].CGColor;
       //将路径填充颜色设置为透明
       _progressLayer.fillColor=
[UIColorclearColor].CGColor;
 //用progressLayer来截取渐变层
    [self.gradientLayersetMask:self.progressLayer];
3.绘制百分比向下箭头Label
/**
 绘制向下的三角形(这里的路径超出了Label,当然我们只要不截取超出部分就行了,不用管原始Label中的文字是否居中)
 */
-(void)drawTriangle{
   //圆角矩形
   UIBezierPath
*path = [UIBezierPathbezierPathWithRoundedRect:_labPercent.framecornerRadius:3];
   //三角形
   UIBezierPath
*trianglePath = [[UIBezierPathalloc]init];
    [trianglePathmoveToPoint:CGPointMake(_percentView.frame.size.width/2-2,_percentView.frame.size.height-5)];;
    [trianglePathaddLineToPoint:CGPointMake(_percentView.frame.size.width/2,_percentView.frame.size.height)];
    [trianglePathaddLineToPoint:CGPointMake(_percentView.frame.size.width/2+2,_percentView.frame.size.height-5)];
   //扩展绘制路径
    [pathappendPath:trianglePath];
   CAShapeLayer
*fillLayer = [CAShapeLayerlayer];
    fillLayer.path=
path.CGPath;
    fillLayer.fillColor=

kBaseColor.CGColor;
 #warning必须将他添加到最下一层,否则会遮挡其他图层
//    [_labPercent.layer addSublayer:fillLayer];
    [_labPercent.layerinsertSublayer:fillLayeratIndex:0];
}
4.动画
//图层直线的轨迹
   UIBezierPath
*path = [UIBezierPathbezierPath];
    [pathmoveToPoint:CGPointMake(0,0)];
    [pathaddLineToPoint:CGPointMake(_animationView.frame.size.width,0)];
   _progressLayer.path=
path.CGPath;

   self.progressLayer.strokeEnd=

0.0;
   //动画时间
   CGFloat
duration =

_animationTime;
   //进度程度
   CGFloat
progress =

_percent;
   //strokeEnd

动画到某个点结束
   CABasicAnimation
*animate = [CABasicAnimationanimationWithKeyPath:@"strokeEnd"];
    animate.removedOnCompletion=

NO;
    animate.fillMode=

kCAFillModeForwards;
    animate.duration=
duration;
    animate.fromValue=

@0.0;
#warning存在偏差,目前不知道原因
    animate.toValue=

@(progress-0.02);
   //为图层添加动画
    [self.progressLayeraddAnimation:animateforKey:@"anim1"];
   
   //百分比标签动画(iOS
10在layoutSubView中失效???)
    _percentView.center=

CGPointMake(0,_percentView.center.y);
#warning此处使用延迟,使动画生效了
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(0.01*

NSEC_PER_SEC)),dispatch_get_main_queue(),
^{
        [UIViewanimateWithDuration:_animationTimeanimations:^{
           
           _percentView.center=

CGPointMake(self.frame.size.width*_percent,_percentView.center.y);
        }];
    });
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 绘图 动态