Skip to Content

Shapes trong SwiftUI

1. Các Shape cơ bản

// Rectangle Rectangle() .fill(.blue) .frame(width: 100, height: 100) // Rounded Rectangle RoundedRectangle(cornerRadius: 16) .fill(.green) .frame(width: 150, height: 100) // Circle Circle() .fill(.red) .frame(width: 100, height: 100) // Ellipse Ellipse() .fill(.orange) .frame(width: 150, height: 100) // Capsule Capsule() .fill(.purple) .frame(width: 150, height: 50)

2. Fill và Stroke

// Fill Circle() .fill(.blue) .frame(width: 100, height: 100) // Stroke (viền) Circle() .stroke(.blue, lineWidth: 4) .frame(width: 100, height: 100) // Stroke style Circle() .stroke(.red, style: StrokeStyle( lineWidth: 4, lineCap: .round, lineJoin: .round, dash: [10, 5] // Dashed line )) .frame(width: 100, height: 100) // Fill + Stroke ZStack { Circle() .fill(.blue.opacity(0.3)) Circle() .stroke(.blue, lineWidth: 3) } .frame(width: 100, height: 100)

3. Gradient Fills

// Linear Gradient Rectangle() .fill( LinearGradient( colors: [.blue, .purple], startPoint: .topLeading, endPoint: .bottomTrailing ) ) .frame(width: 200, height: 100) // Radial Gradient Circle() .fill( RadialGradient( colors: [.yellow, .orange, .red], center: .center, startRadius: 0, endRadius: 100 ) ) .frame(width: 200, height: 200) // Angular Gradient Circle() .fill( AngularGradient( colors: [.red, .orange, .yellow, .green, .blue, .purple, .red], center: .center ) ) .frame(width: 200, height: 200)

4. Custom Shapes

struct Triangle: Shape { func path(in rect: CGRect) -> Path { var path = Path() path.move(to: CGPoint(x: rect.midX, y: rect.minY)) path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) path.closeSubpath() return path } } // Sử dụng Triangle() .fill(.orange) .frame(width: 100, height: 100)

Star Shape

struct Star: Shape { let points: Int let innerRatio: CGFloat func path(in rect: CGRect) -> Path { let center = CGPoint(x: rect.midX, y: rect.midY) let outerRadius = min(rect.width, rect.height) / 2 let innerRadius = outerRadius * innerRatio var path = Path() let angleIncrement = .pi * 2 / CGFloat(points * 2) for i in 0..<(points * 2) { let radius = i.isMultiple(of: 2) ? outerRadius : innerRadius let angle = CGFloat(i) * angleIncrement - .pi / 2 let point = CGPoint( x: center.x + cos(angle) * radius, y: center.y + sin(angle) * radius ) if i == 0 { path.move(to: point) } else { path.addLine(to: point) } } path.closeSubpath() return path } } Star(points: 5, innerRatio: 0.4) .fill(.yellow) .frame(width: 100, height: 100)

5. clipShape

// Clip image thành hình tròn Image("avatar") .resizable() .aspectRatio(contentMode: .fill) .frame(width: 100, height: 100) .clipShape(Circle()) // Clip với RoundedRectangle Image("banner") .resizable() .aspectRatio(contentMode: .fill) .frame(width: 300, height: 200) .clipShape(RoundedRectangle(cornerRadius: 20))

6. Overlay và Background

// Badge Text("5") .font(.caption) .foregroundColor(.white) .padding(8) .background(Circle().fill(.red)) // Card với shadow VStack { Text("Card Content") } .padding() .background( RoundedRectangle(cornerRadius: 16) .fill(.white) .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4) ) // Outlined shape Circle() .fill(.blue.opacity(0.1)) .overlay( Circle() .stroke(.blue, lineWidth: 2) ) .frame(width: 100, height: 100)

7. Shapes với Animation

struct AnimatedCircle: View { @State private var isAnimating = false var body: some View { Circle() .stroke( LinearGradient( colors: [.blue, .purple], startPoint: .topLeading, endPoint: .bottomTrailing ), lineWidth: 8 ) .frame(width: 100, height: 100) .rotationEffect(.degrees(isAnimating ? 360 : 0)) .animation( .linear(duration: 2).repeatForever(autoreverses: false), value: isAnimating ) .onAppear { isAnimating = true } } }

8. Progress Indicators

struct CircularProgress: View { var progress: Double // 0.0 - 1.0 var body: some View { ZStack { // Background circle Circle() .stroke(.gray.opacity(0.2), lineWidth: 10) // Progress circle Circle() .trim(from: 0, to: progress) .stroke( .blue, style: StrokeStyle(lineWidth: 10, lineCap: .round) ) .rotationEffect(.degrees(-90)) // Text Text("\(Int(progress * 100))%") .font(.title2.bold()) } .frame(width: 100, height: 100) } } CircularProgress(progress: 0.75)

📝 Tóm tắt

ShapeMô tả
RectangleHình chữ nhật
RoundedRectangleHCN bo góc
CircleHình tròn
EllipseHình elip
CapsuleHình viên thuốc

Key modifiers: .fill(), .stroke(), .clipShape(), .overlay()

Last updated on