티스토리 뷰
반응형
// https://github.com/TheAppWizard/RadarChart
/// 방사형 차트
struct RadarChart: View {
let data: [Double]
let labels: [String]
let maxValues: [Double]
let shapeColor: Color
let frameHeight: CGFloat?
let frameWidth: CGFloat?
init(data: [Double], labels: [String], maxValues: [Double], shapeColor: Color, frameHeight: CGFloat? = nil, frameWidth: CGFloat? = nil) {
self.data = data
self.labels = labels
self.maxValues = maxValues
self.shapeColor = shapeColor
self.frameHeight = frameHeight
self.frameWidth = frameWidth
}
var body: some View {
GeometryReader { geometry in
ZStack {
RadarChartShape(data: data, maxValues: maxValues, frameSize: geometry.size, shapeColor: shapeColor)
RadarChartLabels(labels: labels, frameSize: geometry.size)
}
}
.frame(width: frameWidth, height: frameHeight)
}
}
struct RadarChartShape: View {
let data: [Double]
let maxValues: [Double]
let frameSize: CGSize
let shapeColor: Color
var body: some View {
ZStack {
Path { path in
let radius = min(frameSize.width, frameSize.height) / 2
let center = CGPoint(x: frameSize.width / 2, y: frameSize.height / 2)
let angle = 2 * .pi / Double(data.count)
for i in 0..<data.count {
let currentAngle = Double(i) * angle - .pi / 2
let x = center.x + CGFloat(radius * cos(currentAngle))
let y = center.y + CGFloat(radius * sin(currentAngle))
if i == 0 {
path.move(to: CGPoint(x: x, y: y))
} else {
path.addLine(to: CGPoint(x: x, y: y))
}
}
path.closeSubpath()
}
.stroke(Color.primary.opacity(0.5), lineWidth: 2)
// Lines from vertices to center
let radius = min(frameSize.width, frameSize.height) / 2
let center = CGPoint(x: frameSize.width / 2, y: frameSize.height / 2)
let angle = 2 * .pi / Double(data.count)
ForEach(0..<data.count, id: \.self) { i in
let currentAngle = Double(i) * angle - .pi / 2
let x = center.x + CGFloat(radius * cos(currentAngle))
let y = center.y + CGFloat(radius * sin(currentAngle))
Path { path in
path.move(to: center)
path.addLine(to: CGPoint(x: x, y: y))
}
.stroke(Color.primary.opacity(0.5), lineWidth: 1)
}
ForEach(0..<data.count, id: \.self) { index in
let radius = min(frameSize.width, frameSize.height) / 2
let center = CGPoint(x: frameSize.width / 2, y: frameSize.height / 2)
let angle = 2 * .pi / Double(data.count)
let currentAngle = Double(index) * angle - .pi / 2
let currentRadius = (data[index] / maxValues[index]) * radius
let x = center.x + CGFloat(currentRadius * cos(currentAngle))
let y = center.y + CGFloat(currentRadius * sin(currentAngle))
Circle()
.fill(shapeColor)
.frame(width: 10, height: 10)
.position(x: x, y: y)
}
Path { path in
let radius = min(frameSize.width, frameSize.height) / 2
let center = CGPoint(x: frameSize.width / 2, y: frameSize.height / 2)
let angle = 2 * .pi / Double(data.count)
for i in 0..<data.count {
let currentAngle = Double(i) * angle - .pi / 2
let currentRadius = (data[i] / maxValues[i]) * radius
let x = center.x + CGFloat(currentRadius * cos(currentAngle))
let y = center.y + CGFloat(currentRadius * sin(currentAngle))
if i == 0 {
path.move(to: CGPoint(x: x, y: y))
} else {
path.addLine(to: CGPoint(x: x, y: y))
}
}
path.closeSubpath()
}
.stroke(shapeColor.opacity(0.5), lineWidth: 1)
//.fill(shapeColor.opacity(0.3)) // 레이더 색 채우기 is only available in iOS 17.0 or newer
}
}
}
struct RadarChartLabels: View {
let labels: [String]
let frameSize: CGSize
var body: some View {
let radius = min(frameSize.width, frameSize.height) / 2
let angle = 2 * .pi / Double(labels.count)
ForEach(0..<labels.count, id: \.self) { index in
let currentAngle = Double(index) * angle - .pi / 2
let x = frameSize.width / 2 + (radius + 20) * CGFloat(cos(currentAngle))
let y = frameSize.height / 2 + (radius + 20) * CGFloat(sin(currentAngle))
Text(labels[index])
.foregroundColor(.primary)
.font(.system(size: 20))
.fontWeight(.bold)
.position(x: x, y: y)
}
}
}
#Preview {
struct Preview: View {
@State private var firstValue: Double = 3
@State private var secondValue: Double = 2
@State private var thirdValue: Double = 2
@State private var fourthValue: Double = 3
@State private var fifthValue: Double = 2
@State private var sixthValue: Double = 2.5
let labels: [String] =
["First", "Second", "Third", "Fourth", "Fifth", "Sixth"]
let maxValues: [Double] = [3, 3, 3, 3, 3, 3]
let shapeColor: Color = .orange
var data: [Double] {
[firstValue, secondValue, thirdValue, fourthValue, fifthValue, sixthValue]
}
var body: some View {
RadarChart(data: data, labels: labels, maxValues: maxValues, shapeColor: shapeColor)
.frame(height: 250)
}
}
return Preview()
}
출처
https://github.com/TheAppWizard/RadarChart
iOS
Swift
Xcode
반응형
'iOS SwiftUI' 카테고리의 다른 글
iOS SwiftUI 팝오버 모달 (Popover Modal Tooltip Dropdown) (0) | 2024.11.01 |
---|---|
iOS SwiftUI Pie Chart (iOS 17 미만 버전) 파이 차트, 원형 그래프, Donut 도넛 (0) | 2024.10.01 |
iOS SwiftUI Custom Slider 커스텀 슬라이더 (제어센터 UI) (0) | 2024.08.01 |
[TIL] iOS SwiftUI 글자수, 단어수, 줄수 세기 + 복사, 공유, 툴바, 키보드 닫기 등 (0) | 2024.07.01 |
iOS SwiftUI 드래그 앤 드롭 Drag And Drop (DND) (0) | 2024.04.01 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- localizing
- Localized
- AppStore
- 아이오에스
- permission
- Authorization
- Xcode
- ios
- SWIFT
- 엑스코드
- 스위프트
- custom segment
- presentationcompactadaptation
- 리젝
- swiftUI
- TabBar
- Language
- 인디케이터
- 로컬라이징
- Reject
- 심사
- SKProductsRequestDelegate
- SKPaymentTransactionObserver
- 프로그레스
- 다국어
- Localizations
- indicator
- 테이블뷰
- TabView
- SKPayment
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함