NSAffineTransform — o que é, tipos de transformações e como aplicar

Autor: IT Sectr Publicado: 2026-07-22 Tempo de leitura: 9 min

NSAffineTransform é uma classe do AppKit (macOS) que representa uma transformação afim em gráficos bidimensionais. Ela encapsula uma matriz 3×3 que descreve uma combinação de translação, escala, rotação e cisalhamento de coordenadas. De acordo com a Documentação da Apple (2026), NSAffineTransform é amplamente usado no Core Graphics para transformar caminhos, pontos e contextos gráficos no macOS.

Pontos Principais

  • NSAffineTransform é uma classe do AppKit para transformações afins no macOS com uma matriz 3×3
  • Transformação afim preserva o paralelismo das linhas, mas pode alterar distâncias e ângulos
  • Operações básicas: translate (translação), scale (escala), rotate (rotação), shear (cisalhamento)
  • As transformações são combinadas através de multiplicação de matrizes — a ordem das operações afeta o resultado
  • NSAffineTransform é aplicado a pontos, tamanhos, caminhos e ao contexto do Core Graphics

O que é NSAffineTransform?

NSAffineTransform é uma classe do framework AppKit, disponível apenas no macOS. Ela representa uma transformação afim no espaço bidimensional através de uma matriz 3×3. Ao contrário do CGAffineTransform do Core Graphics (que está disponível no iOS), NSAffineTransform é um invólucro orientado a objetos sobre a struct CGAffineTransform, adicionando métodos convenientes para trabalhar com NSBezierPath, NSPoint e NSSize.

Uma transformação afim é uma transformação do plano que preserva a relação “o ponto está em uma linha” e o paralelismo das linhas. Em outras palavras, após uma transformação afim, linhas paralelas permanecem paralelas e linhas retas permanecem retas. No entanto, distâncias, ângulos e áreas podem mudar: escala, rotação e cisalhamento são casos especiais de transformações afins.

No iOS, o equivalente do NSAffineTransform é a struct CGAffineTransform do Core Graphics. Ambas as APIs são baseadas no mesmo modelo matemático — uma matriz de transformação afim 3×3 onde a última linha é sempre [0, 0, 1]. A diferença é que NSAffineTransform é uma classe (com retain/release em Objective-C), enquanto CGAffineTransform é uma struct (tipo valor) em Swift e C.

Tipos de transformações afins

NSAffineTransform suporta quatro tipos básicos de transformações: translate (translação), scale (escala), rotate (rotação) e shear (cisalhamento). Cada tipo é representado por um método separado e pode ser aplicado a um objeto de transformação existente ou usado para criar um novo.

OperaçãoMétodo NSAffineTransformParâmetrosEfeito visual
TranslatetranslateXBy:yBy:deltaX, deltaYDesloca o objeto ao longo dos eixos X e Y
ScalescaleBy: / scaleXBy:yBy:factor / scaleX, scaleYAumenta ou reduz o tamanho
RotaterotateByDegrees: / rotateByRadians:ângulo em graus ou radianosGira em torno da origem
ShearAtravés de setTransformStructcomponentes m12, m21 da matrizInclina o objeto ao longo de um eixo

Translate — Translação

Translate adiciona um deslocamento às coordenadas de todos os pontos de um objeto. Os parâmetros deltaX e deltaY definem a quantidade de deslocamento horizontal e vertical, respectivamente. Um valor positivo de deltaX desloca para a direita, deltaY para cima. Translate não altera a forma ou o tamanho do objeto — apenas sua posição.

Scale — Escala

Scale multiplica as coordenadas dos pontos por um fator dado. Com escala uniforme (um único parâmetro), o objeto aumenta ou diminui proporcionalmente. Com escala não uniforme, a forma é distorcida. Um fator de 1,0 mantém o tamanho inalterado, maior que 1,0 aumenta, de 0,0 a 1,0 reduz. Valores negativos criam um reflexo espelhado.

Rotate — Rotação

Rotate gira o objeto em torno da origem por um ângulo dado. Um ângulo de rotação positivo corresponde à rotação anti-horária. rotateByDegrees aceita graus (0–360), rotateByRadians aceita radianos (0–2π). A rotação é sempre realizada em relação ao ponto (0, 0), portanto, para girar em torno de um ponto arbitrário, é necessário combinar rotate com translate.

Representação matricial 3×3

A transformação afim no NSAffineTransform é representada por uma matriz 3×3 onde a última linha é sempre [0, 0, 1]. Esta é a representação matemática padrão que permite representar uma combinação de transformações como um produto de matrizes. A estrutura da matriz é definida através de NSAffineTransformStruct, que contém seis componentes significativos: m11, m12, m21, m22, tX, tY.

Os componentes m11, m12, m21, m22 são responsáveis pela escala, rotação e cisalhamento. Os componentes tX e tY são responsáveis pela translação. Na configuração padrão (matriz identidade), m11 = 1, m22 = 1, e os demais são 0. Para obter os valores atuais da matriz, usa-se transformStruct — a propriedade do NSAffineTransform que retorna uma estrutura NSAffineTransformStruct.

A multiplicação de matrizes é uma operação não comutativa. Isso significa que a ordem de aplicação das transformações importa: translate + rotate dá um resultado diferente de rotate + translate. Ao combinar, NSAffineTransform multiplica a nova matriz à esquerda pela matriz atual: newMatrix = operation × currentMatrix. Portanto, a última transformação adicionada é aplicada primeiro.

Composição de transformações

NSAffineTransform permite combinar múltiplas transformações em um único objeto. Cada chamada a translateXBy:yBy:, scaleBy: ou rotateByDegrees: modifica a matriz interna — multiplica a matriz atual pela matriz da transformação correspondente. Isso permite criar uma transformação complexa a partir de uma sequência de operações simples.

Para inverter uma transformação combinada, usa-se o método invert. A inversa cria uma nova transformação afim que cancela a original: se você aplicar a transformação original a um ponto e depois a invertida, o ponto retorna à sua posição original. A inversão é útil para cancelar uma transformação de contexto antes de desenhar elementos de UI que não devem ser transformados.

Para verificar se uma transformação é identidade (não altera coordenadas), usa-se a propriedade isIdentity. A transformação identidade é uma matriz unitária — multiplicar por ela deixa as coordenadas do ponto inalteradas. Um novo objeto NSAffineTransform é criado como uma transformação identidade. Esta propriedade é útil para otimização: se a transformação é identidade, sua aplicação pode ser ignorada.

Aplicação a objetos e contexto

NSAffineTransform pode ser aplicado a quatro tipos de objetos: NSPoint, NSSize, NSBezierPath e o contexto gráfico NSGraphicsContext. Para cada alvo existe um método separado: transformPoint:, transformSize:, transformBezierPath: e set.

Transformação de pontos e tamanhos

O método transformPoint: multiplica a matriz de transformação pelo vetor de coordenadas do ponto (x, y, 1), retornando a nova posição do ponto. transformSize: funciona de forma semelhante, mas não leva em conta os componentes tX e tY — a translação não é aplicada, apenas escala, rotação e cisalhamento. Isso é útil para transformar vetores e tamanhos que não devem ser deslocados.

Transformação de caminhos NSBezierPath

O método transformBezierPath: cria um novo objeto NSBezierPath, cada ponto do qual é transformado de acordo com a matriz do NSAffineTransform. O caminho original não é modificado — uma cópia com coordenadas transformadas é criada. Esta é uma operação cara para caminhos complexos com um grande número de nós.

Aplicação ao contexto gráfico

O método set aplica a transformação ao contexto gráfico atual (NSGraphicsContext), modificando sua CTM (Current Transformation Matrix). Após chamar set, todo o desenho subsequente neste contexto será transformado. Para transformações temporárias, use saveGraphicsState / restoreGraphicsState antes e depois de set.

Exemplos de código em Swift

Vejamos exemplos práticos do uso de NSAffineTransform em uma aplicação macOS para transformar objetos gráficos.

Criação e composição de transformações

Este exemplo cria um NSAffineTransform que combina translação, rotação e escala. Primeiro, o objeto é deslocado por (100, 50), depois girado 45 graus e, finalmente, escalado 1,5 vezes. A ordem importa: girar após transladar gira em relação à nova origem.

swift
import AppKit

let transform = NSAffineTransform()
transform.translateXBy(100, yBy: 50)
transform.rotateByDegrees(45)
transform.scaleBy(1.5)

// Aplicando ao ponto
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)

// Aplicando ao tamanho
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)

Transformação do contexto para desenho

Este exemplo demonstra a aplicação de NSAffineTransform a um contexto gráfico através de set e concat. Após aplicar a transformação, todo o desenho subsequente é realizado no sistema de coordenadas transformado. Salvar o estado gráfico através de saveGraphicsState permite retornar à matriz original.

swift
func drawWithTransform(in rect: NSRect) {
    guard let ctx = NSGraphicsContext.current
    else { return }

    ctx.saveGraphicsState()

    let xfm = NSAffineTransform()
    xfm.translateXBy(rect.midX, yBy: rect.midY)
    xfm.rotateByDegrees(30)
    xfm.scaleBy(0.8)
    xfm.concat()

    // Desenhando no sistema de coordenadas transformado
    let path = NSBezierPath(roundedRect: NSRect(
        x: -50, y: -50,
        width: 100, height: 100
    ), xRadius: 10, yRadius: 10)
    NSColor.blue.setFill()
    path.fill()

    ctx.restoreGraphicsState()
}

Transformação de um NSBezierPath

Este exemplo demonstra como criar uma cópia de um NSBezierPath com coordenadas transformadas. O caminho original permanece inalterado, e a cópia transformada pode ser desenhada separadamente — isso é útil para criar elementos repetidos em diferentes posições.

swift
func createTransformedTriangle() -> NSBezierPath {
    let triangle = NSBezierPath()
    triangle.move(to: NSPoint(x: 0, y: 0))
    triangle.line(to: NSPoint(x: 100, y: 0))
    triangle.line(to: NSPoint(x: 50, y: 100))
    triangle.close()

    let xfm = NSAffineTransform()
    xfm.translateXBy(200, yBy: 100)
    xfm.scaleXBy(1.5, yBy: 1.5)
    xfm.rotateByDegrees(45)

    let transformed = xfm.transform(triangle)
    return transformed
}

Perguntas Frequentes

Qual a diferença entre NSAffineTransform e CGAffineTransform?

NSAffineTransform é uma classe do AppKit (apenas macOS), enquanto CGAffineTransform é uma struct do Core Graphics (iOS e macOS). NSAffineTransform é um invólucro orientado a objetos e fornece métodos para trabalhar com NSBezierPath. CGAffineTransform é uma struct leve de tipo valor usada com CGPath.

Como girar um objeto em torno do seu centro?

Para girar em torno do centro, execute três passos: 1) transladar para o centro do objeto (deslocar a origem para o centro), 2) girar pelo ângulo desejado, 3) transladar de volta pelo vetor negativo do centro. A combinação translação—rotação—translação dá uma rotação em torno de um ponto arbitrário, em vez de em torno da origem.

Posso usar NSAffineTransform no iOS?

Não, NSAffineTransform está disponível apenas no macOS como parte do AppKit. No iOS, usa-se a struct CGAffineTransform do Core Graphics, que fornece capacidades semelhantes: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation e CGAffineTransformConcat.

Como cancelar uma transformação?

Use o método invert, que retorna a transformação inversa. Se você multiplicar a transformação original pela inversa, obtém uma matriz unitária (transformação identidade). Para aplicação temporária, chame saveGraphicsState antes de set e restoreGraphicsState depois.

Como criar um reflexo espelhado?

Use escala negativa: transform.scaleXBy(-1, yBy: 1) cria um reflexo horizontal, enquanto scaleXBy(1, yBy: -1) cria um reflexo vertical. Para refletir em relação a um eixo arbitrário, combine translate (deslocamento ao eixo), scale com -1 e translate inverso.

Resumo

  • NSAffineTransform é uma classe do AppKit para transformações afins com matriz 3×3 no macOS
  • Quatro tipos básicos: translate (translação), scale (escala), rotate (rotação) e shear (cisalhamento)
  • A matriz 3×3 contém seis componentes significativos: m11, m12, m21, m22, tX, tY
  • A ordem de combinação das transformações afeta o resultado — a multiplicação de matrizes não é comutativa
  • Aplica-se a NSPoint, NSSize, NSBezierPath e ao contexto gráfico através de CTM
  • Inversão através do método invert cancela qualquer transformação afim
  • No iOS, o equivalente é a struct CGAffineTransform do Core Graphics

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também