iOS 가이드 라인 이 있 는 떡 모양 그림 효과 구현(겹 치지 않 음)
먼저 위의 그림 을 그리다.
1.효과 도-w220
그림 에서 모든 부채 형 이 아무리 작 아 도 안내 선 에서 안내 하 는 데 이 터 를 분리 하여 겹 치지 않 습 니 다.
첫걸음
그림 의 데이터 에 모델 을 만들어 야 합 니 다.
@interface DVFoodPieModel : NSObject
/**
*/
@property (copy, nonatomic) NSString *name;
/**
*/
@property (assign, nonatomic) CGFloat value;
/**
*/
@property (assign, nonatomic) CGFloat rate;
@end
두 번 째 단계지금 먼저 떡 그림 중간의 원형 을 만들어 보 세 요.이 건 어렵 지 않 아 요.코드 를 바로 붙 여요.
파일
@interface DVPieCenterView : UIView
@property (strong, nonatomic) UILabel *nameLabel;
@end
파일
@interface DVPieCenterView ()
@property (strong, nonatomic) UIView *centerView;
@end
@implementation DVPieCenterView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.4];
UIView *centerView = [[UIView alloc] init];
centerView.backgroundColor = [UIColor whiteColor];
[self addSubview:centerView];
self.centerView = centerView;
UILabel *nameLabel = [[UILabel alloc] init];
nameLabel.textColor = [UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1];
nameLabel.font = [UIFont systemFontOfSize:18];
nameLabel.textAlignment = NSTextAlignmentCenter;
self.nameLabel = nameLabel;
[centerView addSubview:nameLabel];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.layer.cornerRadius = self.frame.size.width * 0.5;
self.layer.masksToBounds = true;
self.centerView.frame = CGRectMake(6, 6, self.frame.size.width - 6 * 2, self.frame.size.height - 6 * 2);
self.centerView.layer.cornerRadius = self.centerView.frame.size.width * 0.5;
self.centerView.layer.masksToBounds = true;
self.nameLabel.frame = self.centerView.bounds;
}
노출 된 것 은.h 파일 의 namelable 뿐 입 니 다.중간 에 텍스트 를 표시 해 야 할 때 nameLabel 의 text 에 값 을 부여 하면 됩 니 다.세 번 째 단계
이제 UIView 를 계승 하 는 보 기 를 만 들 고 떡 모양 의 그림 과 안내 선,데 이 터 를 그 릴 수 있 습 니 다.
.h 파일 에는 데이터 배열 과 중간 에 표 시 된 텍스트,그리고 draw 방법 이 필요 합 니 다.(draw 방법 은 개인 적 인 습관 입 니 다.데이터 의 모든 할당 이 완 료 된 후에 이 방법 으로 그림 을 그립 니 다)
@interface DVPieChart : UIView
/**
*/
@property (strong, nonatomic) NSArray *dataArray;
/**
*/
@property (copy, nonatomic) NSString *title;
/**
*/
- (void)draw;
@end
draw 방법 을 호출 하기 전에 데이터 의 모든 할당 이 완료 되 었 는 지 확인 해 야 합 니 다.그리 기 작업 은 사실- (void)drawRect:(CGRect)rect
방법 에서 이 루어 졌 기 때문에 h 파일 의 draw 방법 은 시스템 방법 을 호출 하 는 것 입 니 다.m 파일 에서 draw 방법의 실현
- (void)draw {
[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self setNeedsDisplay];
}
[self setNeedsDisplay];
drawRect 방법 을 호출 하 러 왔 습 니 다.[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
이 방법 은 pieChart 에 추 가 된 centerView 를 제거 하 는 것 입 니 다.그렇지 않 으 면 다시 그 릴 때마다 centerView 를 추가 합 니 다.다음은 draw Rect 방법의 실현 입 니 다.
우선 원 의 반지름,중심 점 과 시작 점 을 확정 해 야 한다.
CGFloat min = self.bounds.size.width > self.bounds.size.height ? self.bounds.size.height : self.bounds.size.width;
CGPoint center = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
CGFloat radius = min * 0.5 - CHART_MARGIN;
CGFloat start = 0;
CGFloat angle = 0;
CGFloat end = start;
CHART_MARGIN 은 자신 이 정의 한 매크로 입 니 다.원 은 보기 의 변 에 접선 을 할 수 없습니다.여기 서 저 는 CHARTMARGIN 을 60 으로 설정*제품 의 수요 에 따라 요청 한 데이터 가 비어 있 을 때 순수한 색 의 원 을 표시 하고 안내 선 을 그리 지 않 기 때문에 drawRect 에서 두 가지 상황 으로 나 누 어 이 루어 집 니 다.
```objc
if (self.dataArray.count == 0) {
} else {
}
```
* dataArray 0
```objc
if (self.dataArray.count == 0) {
end = start + M_PI * 2;
UIColor *color = COLOR_ARRAY.firstObject;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:start endAngle:end clockwise:true];
[color set];
//
[path addLineToPoint:center];
[path fill];
}
```
> COLOR_ARRAY , 6 , , ( , )
``` objc
#define COLOR_ARRAY @[\
[UIColor colorWithRed:251/255.0 green:166.9/255.0 blue:96.5/255.0 alpha:1],[UIColor colorWithRed:151.9/255.0 green:188/255.0 blue:95.8/255.0 alpha:1],
[UIColor colorWithRed:245/255.0 green:94/255.0 blue:102/255.0 alpha:1],
[UIColor colorWithRed:29/255.0 green:140/255.0 blue:140/255.0 alpha:1],
[UIColor colorWithRed:121/255.0 green:113/255.0 blue:199/255.0 alpha:1],
[UIColor colorWithRed:16/255.0 green:149/255.0 blue:224/255.0 alpha:1]
]
```
*dataArray 길이 가 0 이 아 닐 때
```objc
for (int i = 0; i < self.dataArray.count; i++) {
DVFoodPieModel *model = self.dataArray[i];
CGFloat percent = model.rate;
UIColor *color = COLOR_ARRAY[i % 6];
start = end;
angle = percent * M_PI * 2;
end = start + angle;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:start endAngle:end clockwise:true];
[color set];
//
[path addLineToPoint:center];
[path fill];
}
```
else 에서 이렇게 하면 각 부채 형 을 그 릴 수 있 습 니 다.
* , centerView
```objc
// label
DVPieCenterView *centerView = [[DVPieCenterView alloc] init];
centerView.frame = CGRectMake(0, 0, 80, 80);
CGRect frame = centerView.frame;
frame.origin = CGPointMake(self.frame.size.width * 0.5 - frame.size.width * 0.5, self.frame.size.height * 0.5 - frame.size.width * 0.5);
centerView.frame = frame;
centerView.nameLabel.text = self.title;
[self addSubview:centerView];
```
네 번 째 단계,회화 가이드 라인 과 데이터안내 선 을 그립 니 다.부채 형 을 그 릴 때 몇 개의 데 이 터 를 확인 하고 이 몇 가지 데이터 에 따라 그립 니 다.
//
CGFloat radianCenter = (start + end) * 0.5;
//
CGFloat lineStartX = self.frame.size.width * 0.5 + radius * cos(radianCenter);
CGFloat lineStartY = self.frame.size.height * 0.5 + radius * sin(radianCenter);
CGPoint point = CGPointMake(lineStartX, lineStartY);
이 그림 은 방금 만 들 었 을 때 겹 쳐 서 제품 의 수요 에 따라 변경 되 었 기 때문에 변수 이름 이 약간 다른 의미 가 있 을 수 있 습 니 다.바 꾸 기 가 불편 합 니 다.저 는 주석 만 잘 할 수 있 습 니 다.여러분 은 주석 을 기준 으로 합 니 다.순서대로 그리 면 안내 선의 위치 가 겹 치지 않 기 때문에 중간 에 있 는 데 이 터 를 먼저 그리고 중간 데이터 양쪽 의 데 이 터 를 그립 니 다.
그러면 위 에서 확인 해 야 할 데 이 터 를 배열 에 순서대로 추가 해 야 합 니 다.
예:원 데 이 터 는@[@1,@2,@3,@4,@5,@6]입 니 다.
가이드 라인 을 그 릴 때 는 데이터 가 필요 합 니 다.@[@3,@2,@1,@4,@5,@6]
그래서 for 순환 에서 이렇게 바 꿔 야 돼 요.
데이터 가 순 서 를 변경 한 후,그 릴 때 모델 데이터 와 색상 데이터 도 순 서 를 변경 해 야 합 니 다.
우선 두 변 수 를 설명 합 니 다.
@interface DVPieChart ()
@property (nonatomic, strong) NSMutableArray *modelArray;
@property (nonatomic, strong) NSMutableArray *colorArray;
@end
else 에서 이렇게 됐어 요.
NSMutableArray *pointArray = [NSMutableArray array];
NSMutableArray *centerArray = [NSMutableArray array];
self.modelArray = [NSMutableArray array];
self.colorArray = [NSMutableArray array];
for (int i = 0; i < self.dataArray.count; i++) {
DVFoodPieModel *model = self.dataArray[i];
CGFloat percent = model.rate;
UIColor *color = COLOR_ARRAY[i];
start = end;
angle = percent * M_PI * 2;
end = start + angle;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:start endAngle:end clockwise:true];
[color set];
//
[path addLineToPoint:center];
[path fill];
//
CGFloat radianCenter = (start + end) * 0.5;
//
CGFloat lineStartX = self.frame.size.width * 0.5 + radius * cos(radianCenter);
CGFloat lineStartY = self.frame.size.height * 0.5 + radius * sin(radianCenter);
CGPoint point = CGPointMake(lineStartX, lineStartY);
if (i <= self.dataArray.count / 2 - 1) {
[pointArray insertObject:[NSValue valueWithCGPoint:point] atIndex:0];
[centerArray insertObject:[NSNumber numberWithFloat:radianCenter] atIndex:0];
[self.modelArray insertObject:model atIndex:0];
[self.colorArray insertObject:color atIndex:0];
} else {
[pointArray addObject:[NSValue valueWithCGPoint:point]];
[centerArray addObject:[NSNumber numberWithFloat:radianCenter]];
[self.modelArray addObject:model];
[self.colorArray addObject:color];
}
}
for 순환 에서 필요 한 데 이 터 를 확 정 했 습 니 다:pointArray、centerArray、self.modelArray、self.colorArray
위 에서 확 정 된 데이터 에 따라 안내 선 을 그립 니 다.논리 가 복잡 합 니 다.방법 을 써 서 그립 니 다.
- (void)drawLineWithPointArray:(NSArray *)pointArray centerArray:(NSArray *)centerArray
for 순환 외 호출
// pointArray centerArray
[self drawLineWithPointArray:pointArray centerArray:centerArray];
다섯 번 째 단계방법 내부 실현
확인 할 데이터 가 있 습 니 다:
1.가이드 라인 길이
2.가이드 라인 의 출발점,종점,전환점
3.가이드 라인 데이터 가 차지 하 는 rect 범위(다음 을 그 릴 때 겹 치 는 지 확인 하 는 데 사용)
아래 에 직접 코드 를 붙 여 실현 합 니 다.주석 을 주의 깊 게 보 세 요.저 는 코드 밖 에 다시 쓰 지 않 겠 습 니 다.
- (void)drawLineWithPointArray:(NSArray *)pointArray centerArray:(NSArray *)centerArray {
// ( )
CGRect rect = CGRectZero;
//
CGFloat width = self.bounds.size.width * 0.5;
for (int i = 0; i < pointArray.count; i++) {
//
NSValue *value = pointArray[i];
//
CGPoint point = value.CGPointValue;
//
CGFloat radianCenter = [centerArray[i] floatValue];
// ( )
UIColor *color = self.colorArray[i % 6];
// ( )
DVFoodPieModel *model = self.modelArray[i];
//
NSString *name = model.name;
NSString *number = [NSString stringWithFormat:@"%.2f%%", model.rate * 100];
// x y
CGFloat x = point.x;
CGFloat y = point.y;
// (x, y)
CGFloat startX = x + 10 * cos(radianCenter);
CGFloat startY = y + 10 * sin(radianCenter);
// (x, y)
CGFloat breakPointX = x + 20 * cos(radianCenter);
CGFloat breakPointY = y + 20 * sin(radianCenter);
// ( +20, , ,+20 )
CGFloat margin = fabs(width - breakPointX) + 20;
//
CGFloat lineWidth = width - margin;
// (x, y)
CGFloat endX;
CGFloat endY;
// , size(width height)
// width lineWidth ,
CGFloat numberWidth = 80.f;
CGFloat numberHeight = 15.f;
CGFloat titleWidth = numberWidth;
CGFloat titleHeight = numberHeight;
// (x, y) frame
CGFloat numberX;// = breakPointX;
CGFloat numberY = breakPointY - numberHeight;
CGFloat titleX = breakPointX;
CGFloat titleY = breakPointY + 2;
// ( )
NSMutableParagraphStyle * paragraph = [[NSMutableParagraphStyle alloc]init];
//
paragraph.alignment = NSTextAlignmentRight;
// x ,
//
//
if (x <= width) { //
endX = 10;
endY = breakPointY;
//
paragraph.alignment = NSTextAlignmentLeft;
numberX = endX;
titleX = endX;
} else { //
endX = self.bounds.size.width - 10;
endY = breakPointY;
numberX = endX - numberWidth;
titleX = endX - titleWidth;
}
if (i != 0) {
// i!=0 , ( rect) rect1( )
CGRect rect1 = CGRectMake(numberX, numberY, numberWidth, titleY + titleHeight - numberY);
CGFloat margin = 0;
if (CGRectIntersectsRect(rect, rect1)) {
//
//
// 1.
// 2.
// 3.
//
if (CGRectContainsRect(rect, rect1)) {//
if (i % self.dataArray.count <= self.dataArray.count * 0.5 - 1) {
//
margin = CGRectGetMaxY(rect1) - rect.origin.y;
endY -= margin;
} else {
//
margin = CGRectGetMaxY(rect) - rect1.origin.y;
endY += margin;
}
} else { //
if (CGRectGetMaxY(rect1) > rect.origin.y && rect1.origin.y < rect.origin.y) { //
margin = CGRectGetMaxY(rect1) - rect.origin.y;
endY -= margin;
} else if (rect1.origin.y < CGRectGetMaxY(rect) && CGRectGetMaxY(rect1) > CGRectGetMaxY(rect)) { //
margin = CGRectGetMaxY(rect) - rect1.origin.y;
endY += margin;
}
}
}
titleY = endY + 2;
numberY = endY - numberHeight;
//
CGRect rect2 = CGRectMake(numberX, numberY, numberWidth, titleY + titleHeight - numberY);
// rect rect
if (numberX == rect.origin.x) {
//
if (rect2.origin.y < rect.origin.y) {
rect = CGRectMake(rect.origin.x, rect2.origin.y, rect.size.width, rect.size.height + rect2.size.height);
} else {
rect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height + rect2.size.height);
}
}
} else {
rect = CGRectMake(numberX, numberY, numberWidth, titleY + titleHeight - numberY);
}
//
if (endX == 10) {
breakPointX = endX + lineWidth;
} else {
breakPointX = endX - lineWidth;
}
breakPointY = endY;
//1.
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(endX, endY)];
[path addLineToPoint:CGPointMake(breakPointX, breakPointY)];
[path addLineToPoint:CGPointMake(startX, startY)];
CGContextSetLineWidth(ctx, 0.5);
//
[color set];
//3.
CGContextAddPath(ctx, path.CGPath);
//4. View ( View layer)(stroke fill)
CGContextStrokePath(ctx);
// ( )
// movePoint,
CGFloat movePoint = -2.5;
UIView *view = [[UIView alloc] init];
view.backgroundColor = color;
[self addSubview:view];
CGRect rect = view.frame;
rect.size = CGSizeMake(5, 5);
rect.origin = CGPointMake(startX + movePoint, startY - 2.5);
view.frame = rect;
view.layer.cornerRadius = 2.5;
view.layer.masksToBounds = true;
//
[name drawInRect:CGRectMake(numberX, numberY, numberWidth, numberHeight) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:9.0], NSForegroundColorAttributeName:color,NSParagraphStyleAttributeName:paragraph}];
// title
[number drawInRect:CGRectMake(titleX, titleY, titleWidth, titleHeight) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:9.0],NSForegroundColorAttributeName:color,NSParagraphStyleAttributeName:paragraph}];
}
}
github 주소 첨부:https://github.com/FireMou/DVPieChart ( 로 컬 다운로드 )총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Swift의 패스트 패스Objective-C를 대체하기 위해 만들어졌지만 Xcode는 Objective-C 런타임 라이브러리를 사용하기 때문에 Swift와 함께 C, C++ 및 Objective-C를 컴파일할 수 있습니다. Xcode는 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.