Как векторные изображения работают в XCode (например, PDF-файлы)?

Как работает векторная поддержка в Xcode 6?

Когда я пытаюсь изменить размер изображения, оно выглядит неровным, что дает?

6 ответов

Решение

Как использовать векторы в Xcode (7 и 6.3+):

  1. Сохраните изображение в формате.pdf с подходящим размером @1x (например, 44x44 для кнопки панели инструментов).
  2. В вашем файле Images.xcassets создайте новый набор изображений.
  3. В Инспекторе Атрибутов установите Коэффициенты Масштабирования на Единственный Вектор.
  4. Перетащите файл PDF в раздел " Все, универсальный ".
  5. Теперь вы можете обращаться к своему изображению по его имени, как и к любому файлу .png.

    UIImage(named: "myImage")
    

Как использовать векторы в более старых версиях Xcode (6.0 - 6.2):

  • Выполните шаги, описанные выше, за исключением шага 3, установите Типы на Векторы.

Как работают векторы в Xcode

Векторная поддержка сбивает с толку в Xcode, потому что, когда большинство людей думают о векторах, они думают об изображениях, которые могут увеличиваться и уменьшаться и при этом хорошо выглядеть. Тем не менее, Xcode 6 и 7 не имеют полной векторной поддержки iOS, поэтому все работает немного по-другому.

Система векторов действительно проста. Это займет у вас .pdf изображение и создает @1x.png, @2x.png, а также @3x.png активы во время сборки. (Вы можете использовать инструмент для проверки содержимого Assets.car, чтобы убедиться в этом.)

Например, предположим, что вы получили foo.pdf который является векторным активом 44x44. Во время сборки он сгенерирует следующие файлы:

  • foo@1x.png в 44x44
  • foo@2x.png в 88x88
  • foo@3x.png в 132x132

Это работает так же для любого размера изображения. Например, если у вас есть bar.pdf 100x100, вы получите:

  • bar@1x.png в 100x100
  • bar@2x.png в 200x200
  • bar@3x.png в 300x300

Последствия:

  • Вы не можете выбрать новый размер для изображения; это будет хорошо смотреться, если вы сохраните размер 44х44. Причина в том, что полная поддержка векторов не реализована. Единственное, что делают эти векторы, это экономит ваше время сохранения ваших изображений. Если у вас есть инструмент (например, скрипт Photoshop), который уже делает этот процесс одностадийным, единственное, что вы получите, используя векторы pdf, - это поддержка будущего (например, если в iOS 9 Apple начинает требовать ресурсы @4x, они просто будут работать), и у вас будет меньше файлов для обслуживания.
  • Вы должны запросить все ваши активы в размере @1x, сохраненные в виде файлов PDF. Среди прочего, это позволит UIImageViews иметь правильный внутренний размер контента.

Почему это (вероятно) работает так:

  • Это делает его обратно совместимым с предыдущими версиями iOS.
  • Изменение размеров векторов может быть сложной вычислительной задачей во время выполнения; реализовав его таким образом, вы не столкнетесь с производительностью.

В Xcode 8 вы все еще можете добавить PDF-файл, создать новый набор изображений, а в инспекторе атрибутов установить параметр "Масштабировать в один масштаб".

Это дополнение к отличному ответу @Senseful.

Как сделать векторные изображения в формате.pdf

Я расскажу, как это сделать в Inkscape, поскольку он бесплатный и с открытым исходным кодом, но другие программы должны быть похожими.

В Inkscape:

  1. Создать новый проект.
  2. Перейдите в "Файл"> "Свойства документа" и задайте для пользовательского размера страницы любой размер @1x (44x44, 100x100 и т. Д.) С единицами измерения в пикселях.
  3. Сделайте свою работу.
  4. Перейдите в Файл> Сохранить как... > Формат документа для печати (*.pdf) > Сохранить> ОК. (В качестве альтернативы вы можете перейти в "Печать"> "Печать в файл"> "Формат вывода: PDF > Печать", но вариантов не так много.)

Заметки:

  • Как упомянуто в принятом ответе, вы не можете изменить размер своего изображения, потому что XCode все еще производит растеризованные изображения во время сборки. Если вам нужно изменить размер изображения, вы должны создать новый файл.pdf другого размера.
  • Если у вас уже есть изображение.svg с неправильным размером страницы, сделайте следующее:

    1. Изменить размер страницы (Inkscape > Файл> Свойства документа)
    2. Выделите все объекты (Ctrl+A) в рабочей области и измените их размер в соответствии с новым размером страницы. (Удерживайте Ctrl, чтобы сохранить размер аспекта.)
  • Чтобы преобразовать файл.svg в формат.pdf, вы также можете найти онлайн-утилиты, которые сделают эту работу за вас. Вот один пример из этого ответа. Преимущество этого состоит в том, что вы можете легко установить размер.pdf.

дальнейшее чтение

Для тех, кто еще не обновился, были внесены изменения в Xcode 9 (iOS 11).

Что нового в Cocoa Touch (сессия WWDC 2017) (@ 32: 55) https://developer.apple.com/videos/play/wwdc2017/201/

В двух словах, каталог активов теперь включает новый флажок в инспекторе атрибутов под названием "Сохранить векторные данные". Если этот флажок установлен, данные PDF будут включены в скомпилированный двоичный файл, что, конечно, увеличит его размер. Но это дает iOS возможность масштабировать векторные данные в обоих направлениях и получать красивые изображения (со своими собственными трудностями). Для iOS ниже 11 используются старые механизмы масштабирования, описанные в ответах вверх.

Xcode и векторное изображение

Растровое изображение PNG масштабный коэффициент @1x, @2x, @3x

Как разработчик вы несете ответственность за установку .png в соответствующий фактор

Официальный документ — Размер и разрешение изображения

Векторное изображение PDF против SVG

Векторный PDF(формат переносимых документов) Не все файлы PDF являются векторными файлами.

  • Xкод 6 - single scale; время сборки; PDF -> PNG(@1x, @2x, @3x);
  • Xcode 9 и iOS 11 — ; время выполнения; Динамический масштаб

SVG(масштабируемая векторная графика)

  • Xcode 12 и iOS < 13 - SVG -> PNG(@1x, @2x, @3x)
  • Xcode 12 и iOS 13 - ; время работы; Динамический масштаб

Диф

  • В большинстве случаев SVG меньше, чем PDF
  • SVG доступен для чтения и редактирования в текстовом редакторе.

Эксперименты

Если вы создаете проект и строите его (не только для конкретного устройства - Any iOS device) с файлами .pdf и .svg вы увидите, что они работают одинаково

  • генерируются png-файлы (файл Assets.car [О программе] )
  • когда вы выбираете и Individual scales(НЕТ Single scale) результатом будет Динамический масштаб

Preserve Vector Dataвыключить и включить

Сгенерированные файлы

Вы можете использовать обычные PDF-файлы внутри вашего проекта в качестве векторных изображений и рендерить изображения любого размера, используя это расширение. Этот способ намного лучше, потому что iOS не будет генерировать изображения.PNG из ваших файлов PDF, плюс вы можете отображать изображения любого размера, который вы хотите:

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
    }
}

}

Другие вопросы по тегам