这次简单的写一个关于雷达数据显示的案列,实现简单,主要用UIBezierPath
以及CAShapeLayer
,如下图:
具体实现:
思路:如何绘制上图中的六边形?我们只需要确定最外层六边形的边长(确定大小)和六边形的中心点的坐标(确定位置)。绘制几层六边形可以随意控制(把边平分几段)。然后添加每个顶点旁边的文本。最后根据相应的数据值绘制layer
(颜色层)。
实现代码:
1、初始化默认数据:
- (void)configureDefaultData
{
_lineWidth = 0.5;
_valueWidth = 0.8;
_maxValue = 100.0;///<最大值,默认100(对应产品需求数据里面的最大值)
_perAngle = 2 * M_PI / SideCount;
//默认六边形在view的中间位置(任意调整)
_centerPoint = CGPointMake(self.yy_width * 0.5, self.yy_height * 0.5);
//根据中间点和边长就可以确定六边形最外层六个点坐标;如果知道层数那么就可以确定每一层六边形的每个点的坐标
_sideLength = 100.0;//默认六边形边长为 100
_layerCount = 5;//默认层数为 5 层
_layerStrokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.2];
_layerFillColor = [UIColor clearColor];
}
2、绘制六边形:
//分割 num 后每格长度
CGFloat dLength = _sideLength / _layerCount;
// CGFloat sinV = sin(Degrees_To_Radians(30));//sin30度值
// CGFloat cosV = cos(Degrees_To_Radians(30));//cos30度值
// 绘制 num 个六边形
for (NSInteger i = 0; i < _layerCount; i ++) {
//每一层边长
CGFloat perSideLength = _sideLength - (dLength * i);
//每一层贝塞尔曲线
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
//确定六个顶点坐标
for (NSInteger j = 0; j < SideCount; j++) {
CGPoint tempPoint = CGPointMake(_centerPoint.x - perSideLength * cos(_perAngle * (j+1)) ,_centerPoint.y - perSideLength * sin(_perAngle * (j+1)));
if (j == 0) {
[bezierPath moveToPoint:tempPoint];
} else {
[bezierPath addLineToPoint:tempPoint];
}
//保存最外层六边形的六个顶点坐标
if (i == 0) {
[self.outerLayerPoints addObject:[NSValue valueWithCGPoint:tempPoint]];
}
}
[bezierPath closePath];
CAShapeLayer *aLayer = [CAShapeLayer layer];
aLayer.lineWidth = _lineWidth;
aLayer.fillColor = _layerFillColor.CGColor;
aLayer.strokeColor = _layerStrokeColor.CGColor;
aLayer.lineCap = kCALineCapSquare;
aLayer.path = bezierPath.CGPath;
[self.layer addSublayer:aLayer];
}
//各个定点向中心点连线
for (NSInteger i = 0; i < self.outerLayerPoints.count; i++) {
CGPoint point = [self.outerLayerPoints[i] CGPointValue];
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:point];
[bezierPath addLineToPoint:_centerPoint];
CAShapeLayer *aLayer = [CAShapeLayer layer];
aLayer.lineWidth = _lineWidth;
aLayer.fillColor = _layerFillColor.CGColor;
aLayer.strokeColor = _layerStrokeColor.CGColor;
aLayer.lineCap = kCALineCapSquare;
aLayer.path = bezierPath.CGPath;
[self.layer addSublayer:aLayer];
}
3、绘制数据值层:
- (void)initValuePoint
{
//移除之前的值layer
for (CAShapeLayer *layer in self.layerArray) {
[layer removeFromSuperlayer];
}
[self.layerArray removeAllObjects];
for (NSInteger i = 0; i < _values.count; i ++) {
NSArray *templeValues = _values[i];
//绘制
UIBezierPath *path = [UIBezierPath bezierPath];
for (NSInteger j = 0; j < templeValues.count; j++) {
CGFloat value = [[templeValues objectAtIndex:j] floatValue];
//注意:这里最大值以及边长默认设置都是100
//value = value > _sideLength ? _sideLength : value;
//换算
value = (value / _maxValue) * _sideLength > _sideLength ? _sideLength : (value / _maxValue) * _sideLength;
CGPoint tempPoint = CGPointMake(_centerPoint.x - value * cos(_perAngle * (j+1)) ,_centerPoint.y - value * sin(_perAngle * (j+1)));
if (j == 0) {
[path moveToPoint:tempPoint];
} else {
[path addLineToPoint:tempPoint];
}
}
[path closePath];
CGFloat red = arc4random() % 256;
CGFloat green = arc4random() % 256;
CGFloat blue = arc4random() % 256;
CAShapeLayer *shaper = [CAShapeLayer layer];
shaper.path = path.CGPath;
shaper.lineWidth = _valueWidth;
//如果有颜色就采用用户赋值的颜色;如果没有颜色就随机颜色
if (self.valueFillColors.count == self.values.count) {
shaper.fillColor = self.valueFillColors[i].CGColor;
} else {
shaper.fillColor = [UIColor colorWithRed:red/256.0 green:green/256.0 blue:blue/256.0 alpha:0.4].CGColor;
}
if (self.valueStrokeColors.count == self.values.count) {
shaper.strokeColor = self.valueStrokeColors[i].CGColor;
} else {
shaper.strokeColor = [UIColor colorWithRed:red/256.0 green:green/256.0 blue:blue/256.0 alpha:0.7].CGColor;
}
[self.layer addSublayer:shaper];
[self.layerArray addObject:shaper];
}
}
4、添加顶点处文案:
- (void)initLabel
{
//移除之前的label
for (UILabel *label in self.labelArray) {
[label removeFromSuperview];
}
[self.labelArray removeAllObjects];
//label的高度这里写死,可以根据需求设置宽度
CGFloat labelH = 20.0;
CGFloat fontSize = 15.0;
CGFloat space = 5.0;
for (NSInteger i = 0; i < _textArray.count; i++) {
CGPoint point = [self.outerLayerPoints[i] CGPointValue];
CGFloat width = [self sizeOfStringWithMaxSize:CGSizeMake(MAXFLOAT, labelH) textFont:fontSize aimString:_textArray[i]].width;
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, labelH)];
titleLabel.font = [UIFont systemFontOfSize:fontSize];
titleLabel.textColor = [[UIColor grayColor] colorWithAlphaComponent:0.6];
titleLabel.text = _textArray[i];
[self addSubview:titleLabel];
switch (i) {
case 0:
titleLabel.center = CGPointMake(point.x, point.y - labelH / 2 - space);
break;
case 1:
titleLabel.center = CGPointMake(point.x, point.y - labelH / 2 - space);
break;
case 2:
titleLabel.center = CGPointMake(point.x + width / 2 + space, point.y);
break;
case 3:
titleLabel.center = CGPointMake(point.x, point.y + labelH / 2 + space);
break;
case 4:
titleLabel.center = CGPointMake(point.x, point.y + labelH / 2 + space);
break;
case 5:
titleLabel.center = CGPointMake(point.x - width / 2 -space, point.y);
break;
default:
break;
}
[self.labelArray addObject:titleLabel];
}
}
5、外部调用方式:
- (HexagonBerizeView *)hexagonView
{
if (_hexagonView == nil) {
_hexagonView = [[HexagonBerizeView alloc] initWithFrame:CGRectMake(0, 64, ScreenWidth, 300)];
_hexagonView.textArray = @[@"客户关系",@"产品",@"价格",@"品牌",@"服务",@"其他"];;
_hexagonView.valueFillColors = @[[UIColor colorWithRed:7/ 256.0 green:71/256.0 blue:151 / 256.0 alpha:0.4],[UIColor colorWithRed:255/ 256.0 green:0/256.0 blue:0 / 256.0 alpha:0.4]];
_hexagonView.valueStrokeColors = @[[UIColor colorWithRed:7/ 256.0 green:71/256.0 blue:151 / 256.0 alpha:0.7],[UIColor colorWithRed:255/ 256.0 green:0/256.0 blue:0 / 256.0 alpha:0.7]];
//这里最大值取100 (根据需求而定)
_hexagonView.values = @[@[@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100)],
@[@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100),@(arc4random() % 100)]];
}
return _hexagonView;
}
[self.view addSubview:self.hexagonView];
Demo下载地址:https://github.com/MichaelSSY/HexagonBerizeView