一.动态折线图效果图
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);
}];
});
---------------------
作者:Jneth
来源:CSDN
原文:https://blog.csdn.net/u010008647/article/details/78214366
版权声明:本文为博主原创文章,转载请附上博文链接!