Como as imagens vetoriais funcionam no Xcode (arquivos PDF)?

176

Como o suporte a vetores funciona no Xcode 6?

Quando tento redimensionar uma imagem, ela parece irregular, o que dá?

Sensível
fonte

Respostas:

351

Como usar vetores no Xcode (7 e 6.3+):

  1. Salve uma imagem como um arquivo .pdf no tamanho @ 1x adequado (por exemplo, 24x24 para um botão da barra de ferramentas ).
  2. No seu arquivo Images.xcassets , crie um novo conjunto de imagens .
  3. No Inspetor de atributos , defina os fatores de escala como Vetor único .
  4. Arraste e solte seu arquivo pdf na seção Todos, Universal .
  5. Agora você pode se referir à sua imagem pelo nome, assim como faria com qualquer arquivo .png .

    UIImage(named: "myImage")

Como usar vetores em versões mais antigas do Xcode (6.0 - 6.2):

  • Siga as etapas acima, exceto na etapa 3, defina Tipos como Vetores .

Como os vetores funcionam no Xcode

O suporte a vetores é confuso no Xcode, porque quando a maioria das pessoas pensa em vetores, elas pensam em imagens que podem aumentar e diminuir a escala e ainda parecerem boas. No entanto, o Xcode 6 e 7 não tem suporte completo para vetores para iOS, portanto, as coisas funcionam de maneira um pouco diferente.

O sistema vetorial é realmente simples . Leva a sua .pdfimagem, e cria @1x.png, @2x.pnge @3x.pngativos em tempo de compilação . (Você pode usar uma ferramenta para examinar o conteúdo de Assets.car para verificar isso.)

Por exemplo, suponha que você receba foo.pdfum ativo vetorial de 44x44. No momento da construção, ele gera os seguintes arquivos:

Isso funciona da mesma forma para qualquer imagem de tamanho. Por exemplo, se você possui bar.pdf100 x 100, receberá:


Implicações:

  • Você não pode escolher um novo tamanho para a imagem ; só ficará bem se você mantiver o tamanho de 44x44. O motivo é que o suporte total a vetores não é implementado . A única coisa que esses vetores fazem é poupar o tempo de salvar seus recursos de imagem. Se você possui uma ferramenta (por exemplo, um script do Photoshop) que já faz deste processo uma etapa, a única coisa que você ganha com o uso de vetores pdf é o suporte à prova de futuro (por exemplo, se no iOS 9 a Apple começar a exigir recursos @ 4x, isso funcionará apenas) e você terá menos arquivos para manter .
  • Você deve solicitar todos os seus ativos no tamanho @ 1x, salvos como arquivos PDF . Entre outras coisas, isso permitirá que UIImageViews tenha o tamanho de conteúdo intrínseco correto.

Por que (provavelmente) funciona desta maneira:

  • Isso o torna compatível com versões anteriores do iOS.
  • Redimensionar vetores pode ser uma tarefa intensiva computacional em tempo de execução; Ao implementá-lo dessa maneira, não há ocorrências de desempenho .
Sensível
fonte
8
Bom escrever. Isso é discutido na Sessão 411 da WWDC em 2014 - "O que há de novo no Interface Builder", às 44:13. Observe que eles dizem que a rasterização é feita no momento da construção. Também é interessante que no MAC ele use vetores em tempo de execução. Em algum momento distante no futuro, espero que o iOS também.
Mike Vosseller
15
Infelizmente, não dimensiona os valores da fatia. Portanto, se você cortar cantos em 5, não o escalará para 10 e 15 para as imagens 2x e 3x.
Jesse
5
@Jesse se você quiser escalar os valores fatia, você pode fazê-lo sozinho em código usando resizableImageWithCapInsets:e dividindo seus valores fatia por[UIScreen mainScreen].scale
Arie Litovsky
1
Para esclarecer sugestão @ArieLitovsky na corte: você deve remover o corte de ativos e movê-lo para o código, algo comoCGFloat scale = [UIScreen mainScreen].scale; UIImage *image = [[UIImage imageNamed:@"my_unsliced_asset"] resizableImageWithCapInsets:UIEdgeInsetsMake(10 * scale, 11 * scale, 12 * scale, 13 * scale)];
glyuck
6
Como faço isso para o XCode 8? a opção parece ter desaparecido!
Gerald
26

No Xcode 8, você ainda pode adicionar um pdf, criar um novo conjunto de imagens e, no Inspetor de atributos, definir a opção Escalas para escala única. insira a descrição da imagem aqui

Maria
fonte
15

Este é um complemento à excelente resposta de @Senseful.

Como criar imagens vetoriais no formato .pdf

Vou dizer como fazer isso no Inkscape, pois é gratuito e de código aberto, mas outros programas devem ser semelhantes.

No Inkscape:

  1. Crie um novo projeto.
  2. Vá para Arquivo> Propriedades do documento e defina o tamanho da página personalizada para o tamanho @ 1x (44x44, 100x100, etc) com as unidades em px.
  3. Faça seu trabalho artístico.
  4. Vá para Arquivo> Salvar como ...> Formato de documento imprimível (* .pdf)> Salvar> OK. (Como alternativa, você pode ir para Imprimir> Imprimir em arquivo> Formato de saída: PDF> Imprimir, mas não há tantas opções.)

Notas:

  • Como mencionado na resposta aceita, você não pode redimensionar sua imagem porque o Xcode ainda produz as imagens rasterizadas em tempo de criação. Se você precisar redimensionar sua imagem, crie um novo arquivo .pdf com um tamanho diferente.
  • Se você já possui uma imagem .svg com o tamanho de página errado, faça o seguinte:

    1. Alterar o tamanho da página (Inkscape> Arquivo> Propriedades do documento)
    2. Selecione todos os objetos (Ctrl + A) no espaço de trabalho e redimensione-os para caber no novo tamanho da página. (Mantenha pressionada a tecla Ctrl para manter o tamanho do aspecto.)
  • Para converter um arquivo .svg em um .pdf, você também pode encontrar utilitários online para fazer o trabalho por você. Aqui está um exemplo de esta resposta . Isso tem o benefício de permitir que você defina o tamanho .pdf facilmente.

Leitura adicional

Suragch
fonte
12

Para quem ainda não atualizou, houve alterações no Xcode 9 (iOS 11).

O que há de novo no Cocoa Touch (WWDC 2017 Session 201) (@ 32: 55) https://developer.apple.com/videos/play/wwdc2017/201/

Em poucas palavras, o Catálogo de ativos agora inclui a nova caixa de seleção no Inspetor de atributos denominada "Preservar dados vetoriais". Quando marcado, os dados em PDF serão incluídos no binário compilado, aumentando seu tamanho, é claro. Mas isso permite ao iOS dimensionar os dados vetoriais em ambas as direções e fornecer imagens agradáveis ​​(com suas próprias dificuldades). Para iOS abaixo de 11, os mecanismos de escala antigos descritos nas respostas para cima são usados.

Dren
fonte
1

Você pode usar arquivos PDF normais dentro do seu projeto como imagens vetoriais e renderizar imagens de qualquer tamanho usando esta extensão. Dessa maneira, é muito melhor porque o iOS não gera imagens .PNG a partir de seus arquivos PDF, além de você poder renderizá-las com o tamanho que desejar:

    extension UIImage {

    static func fromPDF(filename: String, size: CGSize) -> UIImage? {
        guard let path = Bundle.main.path(forResource: filename, ofType: "pdf") else { return nil }
        let url = URL(fileURLWithPath: path)
        guard let document = CGPDFDocument(url as CFURL) else { return nil }
        guard let page = document.page(at: 1) else { return nil }

        let imageRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(size: size)
            let img = renderer.image { ctx in
                UIColor.white.withAlphaComponent(0).set()
                ctx.fill(imageRect)
                ctx.cgContext.translateBy(x: 0, y: size.height)
                ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
                ctx.cgContext.concatenate(page.getDrawingTransform(.artBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                ctx.cgContext.drawPDFPage(page);
            }

            return img
        } else {
            // Fallback on earlier versions
            UIGraphicsBeginImageContextWithOptions(size, false, 2.0)
            if let context = UIGraphicsGetCurrentContext() {
                context.interpolationQuality = .high
                context.setAllowsAntialiasing(true)
                context.setShouldAntialias(true)
                context.setFillColor(red: 1, green: 1, blue: 1, alpha: 0)
                context.fill(imageRect)
                context.saveGState()
                context.translateBy(x: 0.0, y: size.height)
                context.scaleBy(x: 1.0, y: -1.0)
                context.concatenate(page.getDrawingTransform(.cropBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                context.drawPDFPage(page)
                let image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return image
            }
            return nil
        }
    }

}
Bruno Paulino
fonte
1
Eu tentei isso, mas não parece que dimensiona a imagem para tamanhos de pixel maiores? A própria UIImage que estou recebendo é do tamanho correto; é que a imagem vetorial está centralizada e ainda está no tamanho de pixel original do PDF. (Eu queria dimensioná-lo para o tamanho da UIImage.) Você sabe se isso seria possível?
precisa saber é o seguinte