Blockchain ク gainst to the list

This article uses the current latest version of Xcode 12 + macOS Big sur + iOS14

Shape is a protocol that allows you to draw 2D graphics. Shape fills the color with the foregroundColor Modifier and colors it with the Stroke wrapper.

Built-in basic graphics

SwiftUI has some built-in shapes that inherit the Shape protocol, such as Circle, Rectenge, RoundRectenge, Eclipese, Capsule, etc. You can use it as required, for example, to create a rounded button, which is shaped like a Capsule by setting the modifier to the View’s clipShape Decorator:

  Button(action: {}, label: {
      Text("A button")
          .foregroundColor(.white)
  })
  .frame(width: 300, height: 30, alignment: .center)
  .background(Color.orange)
  .clipShape(Capsule())
Copy the code

The effect is as follows:

Use different built-in graphics for different usage scenarios to quickly complete the UI.

Drawing graphics

Path is passed one by one to a closure with the (inout Path) -> () parameter Path, the Path of the graph to draw.

The usage is similar to that of UIBizerPath in UIKit, with slightly different parameters. Let’s draw a few shapes:

VStack {
		/ / in a straight line
    Path{ path in
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: 150, y: 150))
    }
    .stroke(Color.orange, lineWidth: 5)
    .padding()
		/ / rectangle
    Path{ path in
        path.move(to: CGPoint(x: 0, y: 0))
        path.addRect(CGRect(x: 50, y: 0, width: 100, height: 100))
    }
    .stroke(Color.red, lineWidth: 5)
    .padding()
		/ / arc
    Path{ path in
        path.addArc(center: CGPoint(x: 50, y: 50), radius: 150, startAngle: Angle(radians: 0), endAngle: Angle(degrees: 60), clockwise: false)
    }
    .stroke(Color.blue, lineWidth: 5)
    .padding()
}
Copy the code

Path is also a Shape. You can use Path to crop custom shapes, such as a five-pointed star:

var body: some View {
    VStack {
        Image("Image")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 200, height: 200, alignment: .center)
            .clipShape(Path(path))

    }
}


func path( path: inout Path){
    path.move(to: CGPoint(x: 68.23, y: 133.35))
    path.addLine(to: CGPoint(x: 46.56, y: 144.74))
    path.addLine(to: CGPoint(x: 46.63, y: 144.7))
    path.addCurve(to: CGPoint(x: 24.43, y: 137.91), control1: CGPoint(x: 38.62, y: 148.96), control2: CGPoint(x: 28.68, y: 145.92))
    path.addCurve(to: CGPoint(x: 22.71, y: 127.64), control1: CGPoint(x: 22.75, y: 134.77), control2: CGPoint(x: 22.15, y: 131.16))
    path.addLine(to: CGPoint(x: 26.88, y: 103.3))
    path.addLine(to: CGPoint(x: 26.87, y: 103.38))
    path.addCurve(to: CGPoint(x: 22.23, y: 88.67), control1: CGPoint(x: 27.81, y: 98.01), control2: CGPoint(x: 26.08, y: 92.52))
    path.addLine(to: CGPoint(x: 4.55, y: 71.43))
    path.addLine(to: CGPoint(x: 4.61, y: 71.49))
    path.addCurve(to: CGPoint(x: 4.2, y: 48.28), control1: CGPoint(x: -1.92, y: 65.19), control2: CGPoint(x: -2.1, y: 54.8))
    path.addCurve(to: CGPoint(x: 13.44, y: 43.47), control1: CGPoint(x: 6.68, y: 45.71), control2: CGPoint(x: 9.92, y: 44.02))
    path.addLine(to: CGPoint(x: 37.87, y: 39.91))
    path.addLine(to: CGPoint(x: 37.8, y: 39.92))
    path.addCurve(to: CGPoint(x: 50.35, y: 30.97), control1: CGPoint(x: 43.19, y: 39.17), control2: CGPoint(x: 47.88, y: 35.82))
    path.addLine(to: CGPoint(x: 61.28, y: 8.83))
    path.addLine(to: CGPoint(x: 61.24, y: 8.9))
    path.addCurve(to: CGPoint(x: 83.2, y: 1.34), control1: CGPoint(x: 65.22, y: 0.75), control2: CGPoint(x: 75.05, y: -2.64))
    path.addCurve(to: CGPoint(x: 90.63, y: 8.64), control1: CGPoint(x: 86.4, y: 2.9), control2: CGPoint(x: 89.01, y: 5.46))
    path.addLine(to: CGPoint(x: 101.56, y: 30.78))
    path.addCurve(to: CGPoint(x: 114.13, y: 39.91), control1: CGPoint(x: 103.99, y: 35.71), control2: CGPoint(x: 108.69, y: 39.13))
    path.addLine(to: CGPoint(x: 138.36, y: 43.43))
    path.addLine(to: CGPoint(x: 138.28, y: 43.42))
    path.addCurve(to: CGPoint(x: 152.25, y: 61.97), control1: CGPoint(x: 147.25, y: 44.69), control2: CGPoint(x: 153.51, y: 52.99))
    path.addCurve(to: CGPoint(x: 147.6, y: 71.29), control1: CGPoint(x: 151.75, y: 65.5), control2: CGPoint(x: 150.12, y: 68.77))
    path.addLine(to: CGPoint(x: 129.92, y: 88.52))
    path.addLine(to: CGPoint(x: 129.98, y: 88.47))
    path.addCurve(to: CGPoint(x: 125.09, y: 103.09), control1: CGPoint(x: 126.06, y: 92.25), control2: CGPoint(x: 124.23, y: 97.71))
    path.addLine(to: CGPoint(x: 129.26, y: 127.43))
    path.addLine(to: CGPoint(x: 129.25, y: 127.36))
    path.addCurve(to: CGPoint(x: 115.93, y: 146.38), control1: CGPoint(x: 130.82, y: 136.29), control2: CGPoint(x: 124.86, y: 144.8))
    path.addCurve(to: CGPoint(x: 105.63, y: 144.84), control1: CGPoint(x: 112.42, y: 147), control2: CGPoint(x: 108.8, y: 146.46))
    path.addLine(to: CGPoint(x: 83.77, y: 133.35))
    path.addLine(to: CGPoint(x: 83.84, y: 133.39))
    path.addCurve(to: CGPoint(x: 68.42, y: 133.25), control1: CGPoint(x: 79.03, y: 130.83), control2: CGPoint(x: 73.27, y: 130.78))
    path.addLine(to: CGPoint(x: 68.23, y: 133.35))}Copy the code

The effect is as follows:

Custom graph

You can implement custom shapes by inheriting shapes.

The Shape protocol needs to implement the path method:

func path(in rect: CGRect) -> Path
Copy the code

Path returns a path to draw a graph similar to how path is used above.

You can change the pentacle to a custom Shape

struct Star: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: 68.23, y: 133.35))
        path.addLine(to: CGPoint(x: 46.56, y: 144.74))
        path.addLine(to: CGPoint(x: 46.63, y: 144.7))
        path.addCurve(to: CGPoint(x: 24.43, y: 137.91), control1: CGPoint(x: 38.62, y: 148.96), control2: CGPoint(x: 28.68, y: 145.92))
        path.addCurve(to: CGPoint(x: 22.71, y: 127.64), control1: CGPoint(x: 22.75, y: 134.77), control2: CGPoint(x: 22.15, y: 131.16))
        path.addLine(to: CGPoint(x: 26.88, y: 103.3))
        path.addLine(to: CGPoint(x: 26.87, y: 103.38))
        path.addCurve(to: CGPoint(x: 22.23, y: 88.67), control1: CGPoint(x: 27.81, y: 98.01), control2: CGPoint(x: 26.08, y: 92.52))
        path.addLine(to: CGPoint(x: 4.55, y: 71.43))
        path.addLine(to: CGPoint(x: 4.61, y: 71.49))
        path.addCurve(to: CGPoint(x: 4.2, y: 48.28), control1: CGPoint(x: -1.92, y: 65.19), control2: CGPoint(x: -2.1, y: 54.8))
        path.addCurve(to: CGPoint(x: 13.44, y: 43.47), control1: CGPoint(x: 6.68, y: 45.71), control2: CGPoint(x: 9.92, y: 44.02))
        path.addLine(to: CGPoint(x: 37.87, y: 39.91))
        path.addLine(to: CGPoint(x: 37.8, y: 39.92))
        path.addCurve(to: CGPoint(x: 50.35, y: 30.97), control1: CGPoint(x: 43.19, y: 39.17), control2: CGPoint(x: 47.88, y: 35.82))
        path.addLine(to: CGPoint(x: 61.28, y: 8.83))
        path.addLine(to: CGPoint(x: 61.24, y: 8.9))
        path.addCurve(to: CGPoint(x: 83.2, y: 1.34), control1: CGPoint(x: 65.22, y: 0.75), control2: CGPoint(x: 75.05, y: -2.64))
        path.addCurve(to: CGPoint(x: 90.63, y: 8.64), control1: CGPoint(x: 86.4, y: 2.9), control2: CGPoint(x: 89.01, y: 5.46))
        path.addLine(to: CGPoint(x: 101.56, y: 30.78))
        path.addCurve(to: CGPoint(x: 114.13, y: 39.91), control1: CGPoint(x: 103.99, y: 35.71), control2: CGPoint(x: 108.69, y: 39.13))
        path.addLine(to: CGPoint(x: 138.36, y: 43.43))
        path.addLine(to: CGPoint(x: 138.28, y: 43.42))
        path.addCurve(to: CGPoint(x: 152.25, y: 61.97), control1: CGPoint(x: 147.25, y: 44.69), control2: CGPoint(x: 153.51, y: 52.99))
        path.addCurve(to: CGPoint(x: 147.6, y: 71.29), control1: CGPoint(x: 151.75, y: 65.5), control2: CGPoint(x: 150.12, y: 68.77))
        path.addLine(to: CGPoint(x: 129.92, y: 88.52))
        path.addLine(to: CGPoint(x: 129.98, y: 88.47))
        path.addCurve(to: CGPoint(x: 125.09, y: 103.09), control1: CGPoint(x: 126.06, y: 92.25), control2: CGPoint(x: 124.23, y: 97.71))
        path.addLine(to: CGPoint(x: 129.26, y: 127.43))
        path.addLine(to: CGPoint(x: 129.25, y: 127.36))
        path.addCurve(to: CGPoint(x: 115.93, y: 146.38), control1: CGPoint(x: 130.82, y: 136.29), control2: CGPoint(x: 124.86, y: 144.8))
        path.addCurve(to: CGPoint(x: 105.63, y: 144.84), control1: CGPoint(x: 112.42, y: 147), control2: CGPoint(x: 108.8, y: 146.46))
        path.addLine(to: CGPoint(x: 83.77, y: 133.35))
        path.addLine(to: CGPoint(x: 83.84, y: 133.39))
        path.addCurve(to: CGPoint(x: 68.42, y: 133.25), control1: CGPoint(x: 79.03, y: 130.83), control2: CGPoint(x: 73.27, y: 130.78))
        path.addLine(to: CGPoint(x: 68.23, y: 133.35))
        
        
        return path
    }
}
Copy the code

The code will then be modified

  Image("Image")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 200, height: 200, alignment: .center)
                .clipShape(Star())
Copy the code