Armadilhas no desenho de pétalas de flores SwiftUI: prática do Protocolo de Formas

Registro detalhado do processo completo de desenho de formas de pétalas personalizadas usando o SwiftUI Shape Protocol, incluindo dicas práticas como addQuadCurve e sistema de coordenadas

Origem

Recentemente quis portar meu mini-programa WeChat "花瓣单词挑战" para iOS. Esse jogo envolve formar palavras tocando letras em pétalas. Desenhar pétalas com CSS era simples, mas migrar para SwiftUI foi desafiador.

Como conhecedor intermediário de SwiftUI - tendo criado apenas alguns apps básicos - não sabia por onde começar a desenhar uma pétala. Pesquisei "SwiftUI pétala" no Google e encontrei este artigo. Embora não fosse exatamente o que queria, deu-me um ponto de partida.

O que é o Shape Protocol?

Resumidamente, o Shape Protocol do SwiftUI permite criar formas personalizadas. Basta implementar o método path(in rect: CGRect) -> Path para definir o desenho.

Primeira tentativa: Desenhando arcos com addArc

O artigo usava o método addArc:

struct DaisyPental: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: rect.minX, y: rect.midY))
        path.addArc(
            center: CGPoint(x: rect.maxX, y: rect.midY), 
            radius: rect.maxX*(1/11),
            startAngle: .degrees(90),
            endAngle: .degrees(270),
            clockwise: true
        )
        return path
    }
}

Para entender o código, testei no Xcode com fundo vermelho:

struct ShapTest: View {
    var body: some View {
        DaisyPental()
            .fill(.yellow.gradient)
            .frame(width: 110, height: 20)
            .background(.red)  // Fundo vermelho para visualização
    }
}

Sistema de coordenadas do SwiftUI é contra-intuitivo

Atenção para esta particularidade:

  • Origem no canto superior esquerdo: Não no inferior
  • Eixo X: Positivo para direita (normal)
  • Eixo Y: Positivo para baixo (contra-intuitivo!)

Portanto:

  • rect.minX, rect.minY → Canto superior esquerdo
  • rect.maxX, rect.maxY → Canto inferior direito
  • rect.midX, rect.midY → Centro

Você pode experimentar alterando valores no path.move enquanto observa o preview.

Ângulos do addArc são mais contra-intuitivos

A definição angular do addArc é peculiar:

  • 0° → Direita
  • 90° → Baixo (Não cima!)
  • 180° → Esquerda
  • 270° → Cima

Diferente do sistema matemático padrão.

addQuadCurve: Ferramenta essencial para curvas

Percebi que addArc não servia para minha pétala. Encontrei addQuadCurve no YouTube e funcionou melhor:

path.addQuadCurve(
    to: CGPoint,      // Ponto final
    control: CGPoint  // Ponto de controle
)
  • Ponto inicial: Posição atual
  • Ponto final: Destino da curva
  • Ponto de controle: Define a curvatura

Ajustar o ponto de controle altera visualmente a curva.

Minha implementação final da pétala

Após experimentação, cheguei nesta forma:

import SwiftUI

struct PetalShape: Shape {
    func path(in rect: CGRect) -> Path {
        Path { path in
            // Ponto inicial
            path.move(to: CGPoint(x: rect.minX + 30, y: rect.minY + 30))
            
            // Curva esquerda
            path.addQuadCurve(
                to: CGPoint(x: rect.minX + 30, y: rect.minY - 30),
                control: CGPoint(x: rect.minX - 10, y: rect.minY)
            )
            
            // Ponta da pétala
            path.addQuadCurve(
                to: CGPoint(x: rect.maxX * 1.8, y: rect.minY),
                control: CGPoint(x: rect.midX + 40, y: -rect.maxY + 30)
            )
            
            // Lado direito (retorno ao início)
            path.addQuadCurve(
                to: CGPoint(x: rect.minX + 30, y: rect.minY + 30),
                control: CGPoint(x: rect.midX + 40, y: rect.maxY - 30)
            )
        }
    }
}

Exemplo de uso:

struct ShapeTest: View {
    var body: some View {
        PetalShape()
            .fill(.yellow.gradient)
            .frame(width: 110, height: 110)
    }
}

Próximo passo: Compor a flor completa

Com uma pétala pronta, compor a flor é simples:

  1. Duplicar várias pétalas
  2. Rotacionar com rotationEffect
  3. Ajustar posição com offset
  4. Combinar em uma flor

Lições aprendidas

Conclusões importantes:

  • Sistema de coordenadas: Particularmente contra-intuitivo
  • addQuadCurve > addArc: Superior para curvas naturais
  • Ponto de controle crucial: Experimentação é essencial
  • Preview ao vivo indispensável: Use constantemente o Canvas

Conclusão

Finalmente criei o formato da pétala e continuo o desenvolvimento do "花瓣单词挑战" para iOS, visando lançamento em breve.

Escrevi este artigo para documentar o processo. Se trabalha com formas personalizadas em SwiftUI, espero que ajude!

Referências