Як векторні зображення працюють у Xcode (тобто у форматі PDF)?


177

Як працює векторна підтримка в Xcode 6?

Коли я намагаюся змінити розмір зображення, він виглядає зазубриним, що дає?

Відповіді:


351

Як використовувати вектори в Xcode (7 та 6.3+):

  1. Збережіть зображення у форматі .pdf у відповідному розмірі @ 1x (наприклад, 24x24 для кнопки панелі інструментів ).
  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 в 44х44
  • foo@2x.png в 88х88
  • foo@3x.png в 132х132

Це працює однаково для будь-якого розміру зображення. Наприклад, якщо у вас bar.pdfє 100x100, ви отримаєте:

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

Наслідки:

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

Чому це (мабуть) працює так:

  • Це робить її назад сумісною з попередніми версіями iOS.
  • Зміна розміру векторів може бути обчислювальним завданням під час виконання; реалізуючи це таким чином, не спостерігається показів ефективності .

8
Приємно написати. Це обговорюється у 2014 році на сесії 411 WWDC - «Що нового в Builder інтерфейсу» під час 44:13. Зауважте, що вони кажуть, що растерізація проводиться в час збирання. Також цікаво, що на MAC він використовуватиме вектори під час виконання. У якийсь віддалений момент у майбутньому, сподіваємось, iOS також буде.
Майк Фосселлер,

15
На жаль, він не масштабує значення зрізу. Тож якщо ви наріжте кути на 5, це не буде масштабувати його до 10 та 15 для зображень 2x та 3x.
Джессі

5
@Jesse, якщо ви хочете масштабувати значення зрізів, ви можете зробити це самостійно в коді, використовуючи resizableImageWithCapInsets:та розділивши свої значення скибочки на[UIScreen mainScreen].scale
Arie Litovsky

1
Щоб уточнити пропозицію @ArieLitovsky щодо нарізки: слід видалити фрагмент із активу та перемістити його до коду, щось на кшталтCGFloat scale = [UIScreen mainScreen].scale; UIImage *image = [[UIImage imageNamed:@"my_unsliced_asset"] resizableImageWithCapInsets:UIEdgeInsetsMake(10 * scale, 11 * scale, 12 * scale, 13 * scale)];
glyuck

6
Як це зробити для XCode 8? варіант, здається, зник!
Джеральд

26

У Xcode 8 ви все ще можете додати pdf, створити новий набір зображень, а в інспекторі атрибутів встановити параметр "Ваги" на "Одинична шкала". введіть тут опис зображення


15

Це доповнення до чудової відповіді від @Senseful.

Як зробити векторні зображення у форматі .pdf

Я розповім, як це зробити в Inkscape, оскільки це безкоштовно та з відкритим кодом, але інші програми повинні бути схожими.

У Inkscape:

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

Примітки:

  • Як зазначено у прийнятій відповіді, ви не можете змінити розмір зображення, оскільки Xcode все ще створює растровані зображення під час збирання. Якщо вам потрібно змінити розмір зображення, вам слід створити новий .pdf-файл з іншим розміром.
  • Якщо у вас вже є .svg-зображення, яке має неправильний розмір сторінки, зробіть наступне:

    1. Змінення розміру сторінки (Inkscape> File> Document Properties)
    2. Виберіть усі об'єкти (Ctrl + A) на робочому просторі та змініть їх розмір, щоб вони відповідали новому розміру сторінки. (Утримуйте Ctrl, щоб зберегти розмір аспекту.)
  • Щоб перетворити .svg файл у .pdf, ви також можете знайти інтернет-утиліти, щоб зробити цю роботу за вас. Ось один приклад з цієї відповіді . Це має перевагу, що ви можете легко встановити розмір .pdf.

Подальше читання


12

Для тих, хто досі не оновлювався, відбулися зміни в Xcode 9 (iOS 11).

Що нового в Cocoa Touch (WWDC 2017 Session 201) (@ 32: 55) https://developer.apple.com/videos/play/wwdc2017/201/

Кількома словами, каталог активів тепер включає новий прапорець у інспекторі атрибутів під назвою «Зберегти векторні дані». Якщо встановлено прапорець, дані PDF будуть включені до складеного двійкового файлу, збільшуючи його розмір курсу. Але це дає можливість iOS масштабувати векторні дані в обох напрямках та створювати приємні зображення. (Маючи власні труднощі). Для iOS нижче 11 застосовуються старі механізми масштабування, описані у відповідях угору.


1

Ви можете використовувати звичайні 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
        }
    }

}

1
Я спробував це, але не здається, що він масштабує зображення до великих розмірів пікселів? Сам UIImage, який я отримую, - це правильний розмір; це просто те, що векторне зображення зосереджено і все ще знаходиться в оригінальному розмірі пікселя PDF. (Я хотів масштабувати його до розміру UIImage.) Чи знаєте ви, чи це було б можливо?
DivideByZer0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.