Criando formas SwiftUI complexas usando ferramentas de design

Feb 04 2023
Uma maneira fácil de converter design em código SwiftUI nos dá 5 formas internas para uso em nossos projetos. Eles são Rectangle, RoundedRectangle (que tem um parâmetro de raio de canto), Capsule, Ellipse e Circle.

Uma maneira fácil de converter design em código

fonte: Christina Kirschnerova

SwiftUI nos dá 5 formas internas para uso em nossos projetos.

Eles são Rectangle, RoundedRectangle(que tem um parâmetro de raio de canto), Capsule, Ellipsee Circle.

Vamos vê-lo em ação:

struct ShapesView: View {
    var body: some View {
        VStack (spacing: 10) {
            Rectangle()
                .fill(.pink)
                .frame(width: 100, height: 50)

            RoundedRectangle(cornerRadius: 10, style: .continuous)
                .fill(.purple)
                .frame(width: 100, height: 100)

            Capsule()
                .fill(.blue)
                .frame(width: 150, height: 150)

            Ellipse()
                .fill(.red)
                .frame(width: 150, height: 100)

            Circle()
                .fill(.green)
                .frame(width: 150, height: 250)
        }
    }
}

Xcode versão 14.2

Shapese Pathssão primitivas poderosas que podem ser usadas em muitas situações.

No entanto, há casos em que formas mais complexas são necessárias. A Apple oferece suporte para desenho personalizado com duas ferramentas integradas: Pathse Shapes.

Uma Forma é composta de uma série de Caminhos. Paul Hudson tem uma ótima introdução a essas ferramentas.

Vamos verificar como fica em ação e desenhar um hexágono simples usando o Shapeprotocolo.

struct Hexagon: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let width = rect.width
        let height = rect.height
        let x = rect.midX
        let y = rect.midY
        let side = min(width, height) / 2.0
        let a = side / 2.0
        let b = side * sqrt(3.0) / 2.0
        path.move(to: CGPoint(x: x, y: y - side))
        path.addLine(to: CGPoint(x: x + a, y: y - b))
        path.addLine(to: CGPoint(x: x + a, y: y + b))
        path.addLine(to: CGPoint(x: x, y: y + side))
        path.addLine(to: CGPoint(x: x - a, y: y + b))
        path.addLine(to: CGPoint(x: x - a, y: y - b))
        path.closeSubpath()
        return path
    }
}

      
                
Hexagon created using SwiftUI’s shape method.

Como exemplo, vamos criar um widget neomórfico para nosso aplicativo de rastreamento de hábitos:

Captura de tela de um resultado desejado

Para obter um efeito de profundidade para o número 12, simplesmente usar Text(“12”)modificadores de sombra interna e regular não será suficiente. Precisamos criá-lo usando Shapes.

Para fazer isso, vamos usar uma ferramenta de gráficos vetoriais como Figma (grátis) ou Sketch (pago) para criar as formas.

Primeiro, coloque uma captura de tela de um objeto que você deseja replicar como uma Forma no plano de fundo.

2. Em seguida, comece a desenhar números usando curvas (tecla de atalho “V” no Sketch) na parte superior da captura de tela.

3. Exporte sua Forma criada no formato SVG.

4. Abra o arquivo salvo TextEditore copie o código

Este código é basicamente o nosso desenho SVG.

5. Em seguida, abrahttps://svg-to-swiftui.quassum.com/, (É gratuito, mas considere fazer uma doação como forma de expressar gratidão), cole nosso código no bloco esquerdo e clique em converter. Você pode finalmente copiar o resultado.

fonte: https://svg-to-swiftui.quassum.com/

6. Adicione o recém-gerado Shapeao seu código.

struct MyCustomShape: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let width = rect.size.width
        let height = rect.size.height
        path.move(to: CGPoint(x: 0.19277*width, y: 0.92051*height))
        path.addCurve(to: CGPoint(x: 0.2653*width, y: 0.98843*height), control1: CGPoint(x: 0.20687*width, y: 0.96579*height), control2: CGPoint(x: 0.23104*width, y: 0.98843*height))
        path.addCurve(to: CGPoint(x: 0.33219*width, y: 0.92647*height), control1: CGPoint(x: 0.29955*width, y: 0.98843*height), control2: CGPoint(x: 0.32185*width, y: 0.96777*height))
        path.addLine(to: CGPoint(x: 0.33219*width, y: 0.087*height))
        path.addCurve(to: CGPoint(x: 0.32684*width, y: 0.06301*height), control1: CGPoint(x: 0.33219*width, y: 0.07844*height), control2: CGPoint(x: 0.33033*width, y: 0.07008*height))
        path.addCurve(to: CGPoint(x: 0.24718*width, y: 0.0101*height), control1: CGPoint(x: 0.30949*width, y: 0.02773*height), control2: CGPoint(x: 0.28294*width, y: 0.0101*height))
        path.addCurve(to: CGPoint(x: 0.2008*width, y: 0.02081*height), control1: CGPoint(x: 0.23579*width, y: 0.0101*height), control2: CGPoint(x: 0.21869*width, y: 0.01038*height))
        path.addCurve(to: CGPoint(x: 0.00999*width, y: 0.19972*height), control1: CGPoint(x: 0.17119*width, y: 0.03807*height), control2: CGPoint(x: 0.10759*width, y: 0.0977*height))
        path.addCurve(to: CGPoint(x: 0.00999*width, y: 0.29059*height), control1: CGPoint(x: -0.00333*width, y: 0.23402*height), control2: CGPoint(x: -0.00333*width, y: 0.26431*height))
        path.addCurve(to: CGPoint(x: 0.05958*width, y: 0.31902*height), control1: CGPoint(x: 0.0233*width, y: 0.31686*height), control2: CGPoint(x: 0.03983*width, y: 0.32634*height))
        path.addLine(to: CGPoint(x: 0.18235*width, y: 0.21522*height))
        path.addCurve(to: CGPoint(x: 0.19176*width, y: 0.21836*height), control1: CGPoint(x: 0.18557*width, y: 0.21249*height), control2: CGPoint(x: 0.18979*width, y: 0.2139*height))
        path.addCurve(to: CGPoint(x: 0.19277*width, y: 0.2233*height), control1: CGPoint(x: 0.19242*width, y: 0.21985*height), control2: CGPoint(x: 0.19277*width, y: 0.22156*height))
        path.addLine(to: CGPoint(x: 0.19277*width, y: 0.92051*height))
        path.addLine(to: CGPoint(x: 0.19277*width, y: 0.92051*height))
        path.closeSubpath()
        path.move(to: CGPoint(x: 0.69057*width, y: 0.7981*height))
        path.addCurve(to: CGPoint(x: 0.97169*width, y: 0.34296*height), control1: CGPoint(x: 0.86713*width, y: 0.57524*height), control2: CGPoint(x: 0.96084*width, y: 0.42353*height))
        path.addCurve(to: CGPoint(x: 0.73689*width, y: 0.00042*height), control1: CGPoint(x: 1.01286*width, y: 0.03744*height), control2: CGPoint(x: 0.79508*width, y: 0.00549*height))
        path.addCurve(to: CGPoint(x: 0.54637*width, y: 0.09386*height), control1: CGPoint(x: 0.67965*width, y: -0.00457*height), control2: CGPoint(x: 0.60044*width, y: 0.03569*height))
        path.addCurve(to: CGPoint(x: 0.49384*width, y: 0.25608*height), control1: CGPoint(x: 0.50625*width, y: 0.13702*height), control2: CGPoint(x: 0.48874*width, y: 0.19109*height))
        path.addCurve(to: CGPoint(x: 0.54637*width, y: 0.32849*height), control1: CGPoint(x: 0.49732*width, y: 0.30435*height), control2: CGPoint(x: 0.51483*width, y: 0.32849*height))
        path.addCurve(to: CGPoint(x: 0.60648*width, y: 0.29057*height), control1: CGPoint(x: 0.56918*width, y: 0.32849*height), control2: CGPoint(x: 0.58922*width, y: 0.31585*height))
        path.addLine(to: CGPoint(x: 0.60647*width, y: 0.29056*height))
        path.addCurve(to: CGPoint(x: 0.6279*width, y: 0.24067*height), control1: CGPoint(x: 0.61618*width, y: 0.27632*height), control2: CGPoint(x: 0.6235*width, y: 0.25929*height))
        path.addCurve(to: CGPoint(x: 0.73689*width, y: 0.16131*height), control1: CGPoint(x: 0.6404*width, y: 0.18776*height), control2: CGPoint(x: 0.67673*width, y: 0.16131*height))
        path.addCurve(to: CGPoint(x: 0.80924*width, y: 0.39983*height), control1: CGPoint(x: 0.77971*width, y: 0.16131*height), control2: CGPoint(x: 0.88867*width, y: 0.21187*height))
        path.addCurve(to: CGPoint(x: 0.50041*width, y: 0.82587*height), control1: CGPoint(x: 0.77745*width, y: 0.47504*height), control2: CGPoint(x: 0.58125*width, y: 0.70046*height))
        path.addCurve(to: CGPoint(x: 0.48514*width, y: 0.9152*height), control1: CGPoint(x: 0.47311*width, y: 0.86822*height), control2: CGPoint(x: 0.48396*width, y: 0.90852*height))
        path.addCurve(to: CGPoint(x: 0.5197*width, y: 0.96465*height), control1: CGPoint(x: 0.48792*width, y: 0.93094*height), control2: CGPoint(x: 0.49944*width, y: 0.94742*height))
        path.addCurve(to: CGPoint(x: 0.53583*width, y: 0.97096*height), control1: CGPoint(x: 0.52455*width, y: 0.96877*height), control2: CGPoint(x: 0.53013*width, y: 0.97096*height))
        path.addLine(to: CGPoint(x: 0.94174*width, y: 0.97096*height))
        path.addCurve(to: CGPoint(x: 0.96928*width, y: 0.95989*height), control1: CGPoint(x: 0.95149*width, y: 0.97096*height), control2: CGPoint(x: 0.96104*width, y: 0.96712*height))
        path.addCurve(to: CGPoint(x: 0.99372*width, y: 0.89749*height), control1: CGPoint(x: 0.98557*width, y: 0.94557*height), control2: CGPoint(x: 0.99372*width, y: 0.92477*height))
        path.addCurve(to: CGPoint(x: 0.96211*width, y: 0.82232*height), control1: CGPoint(x: 0.99372*width, y: 0.86647*height), control2: CGPoint(x: 0.98318*width, y: 0.84142*height))
        path.addCurve(to: CGPoint(x: 0.94337*width, y: 0.81459*height), control1: CGPoint(x: 0.95654*width, y: 0.81728*height), control2: CGPoint(x: 0.95002*width, y: 0.81459*height))
        path.addLine(to: CGPoint(x: 0.69517*width, y: 0.81459*height))
        path.addCurve(to: CGPoint(x: 0.68833*width, y: 0.8051*height), control1: CGPoint(x: 0.69139*width, y: 0.81458*height), control2: CGPoint(x: 0.68833*width, y: 0.81033*height))
        path.addCurve(to: CGPoint(x: 0.69057*width, y: 0.7981*height), control1: CGPoint(x: 0.68833*width, y: 0.80243*height), control2: CGPoint(x: 0.68915*width, y: 0.79989*height))
        path.closeSubpath()
        return path
    }
}

8. Finalmente, podemos aplicar todos os modificadores a ele como a um Shapeobjeto regular e obter bons números com um efeito de profundidade.

MyCustomShape()
   .frame(width: 100, height: 100)
   .overlay(
  MyCustomShape()
    .fill(
    .shadow(.inner(color: bgl, radius: 5, x: -5, y: 5))
    .shadow(.inner(color: bgd, radius: 5, x: 5, y: -5)))
    .foregroundColor(colorbg))

É isso! Simples e direto.

Imagine ter que escrever todas essas linhas de código você mesmo. Espero que isso economize algum tempo para que você possa usá-lo para alguma codificação interessante. Até a próxima vez!