web-dev-qa-db-ja.com

ベクター画像はXcode(つまり、pdfファイル)でどのように機能しますか?

Xcode 6でベクターサポートはどのように機能しますか?

画像のサイズを変更しようとすると、ギザギザに見えますが、何が得られますか?

163
Senseful

Xcode(7および6.3+)でベクターを使用する方法:

  1. 画像を適切な@ 1xサイズで。pdfファイルとして保存します(例: ツールバーボタンの場合は24x24 )。
  2. Images.xcassetsファイルで、新しいImage Setを作成します。
  3. Attributes Inspectorで、Scale Factors単一ベクトル
  4. PDFファイルをAll、Universalセクションにドラッグアンドドロップします。
  5. 任意の。pngファイルと同じように、名前で画像を参照できるようになりました。

    UIImage(named: "myImage")
    

Xcodeの古いバージョン(6.0-6.2)でベクターを使用する方法:

  • 手順3を除き、上記の手順に従います。TypesVectorsに設定します。

Xcodeでのベクターの動作

Xcodeではベクターのサポートはわかりにくいです。なぜなら、ほとんどの人がベクターについて考えるとき、彼らは拡大縮小することができ、見栄えの良い画像を考えるからです。ただし、Xcode 6および7はiOSのベクターを完全にサポートしていないため、動作は少し異なります。

ベクトルシステムは本当にシンプルです.pdfイメージを取得し、build time@1x.png@2x.png、および@3x.pngアセットを作成します。 ( Assets.carの内容を調べるツールを使用 これを確認できます。)

たとえば、44x44のベクトル資産であるfoo.pdfが与えられたと仮定します。 build timeで、次のファイルを生成します。

これは、どのサイズの画像でも同じように機能します。たとえば、100x100のbar.pdfがある場合、次のようになります。


含意:

  • 画像の新しいサイズを選択することはできません; 44x44のサイズを維持する場合にのみ、見栄えがよくなります。その理由は、フルベクトルサポートが実装されていないことです。これらのベクターが行う唯一のことは、画像アセットを保存する時間を節約することです。既にこれをワンステッププロセスにするツール(Photoshopスクリプトなど)がある場合、pdfベクトルを使用することで得られるのはfuture-proof support(たとえば、iOS 9でAppleが@ 4xアセットを要求し始めた場合、これらは機能します)、少数のファイルを維持する必要があります
  • すべてのアセットをPDFファイルとして保存された@ 1xサイズで要求する必要があります。とりわけ、これによりUIImageViewsに正しい固有のコンテンツサイズを持たせることができます。

なぜ(おそらく)このように機能するのか:

  • これにより、以前のiOSバージョンと後方互換性があります。
  • ベクトルのサイズ変更は、実行時に計算集約的なタスクになる場合があります。この方法で実装することにより、パフォーマンスの低下はありません
338
Senseful

Xcode 8では、pdfを追加したり、新しい画像セットを作成したり、属性インスペクターで「スケールを単一スケール」オプションに設定したりすることができます。 enter image description here

21
Maria

これは、@ Sensefulによる優れた答えの補足です。

.pdf形式でベクター画像を作成する方法

Inkscapeは無料でオープンソースですが、他のプログラムも同様であるため、Inkscapeでこれを行う方法を説明します。

Inkscapeでは:

  1. 新しいプロジェクトを作成します。
  2. [ファイル]> [ドキュメントのプロパティ]に移動し、カスタムページサイズを@ 1xサイズ(44x44、100x100など)に、px単位で設定します。
  3. アートワークを作成します。
  4. [ファイル]> [名前を付けて保存...]> [印刷可能なドキュメント形式(* .pdf)]> [保存]> [OK]に移動します。 (または、[印刷]> [ファイルに印刷]> [出力形式:PDF>印刷に移動できますが、オプションはそれほど多くありません。)

注:

  • 受け入れられた答えに記載されているように、Xcodeはビルド時にラスタライズされた画像を生成するため、画像のサイズを変更することはできません。画像のサイズを変更する必要がある場合は、異なるサイズの新しい.pdfファイルを作成する必要があります。
  • 間違ったページサイズの.svg画像が既にある場合は、次の手順を実行します。

    1. ページサイズを変更する(Inkscape>ファイル>ドキュメントプロパティ)
    2. ワークスペース上のすべてのオブジェクトを選択し(Ctrl + A)、新しいページサイズに収まるようにサイズを変更します。 (アスペクトサイズを維持するには、Ctrlを押し続けます。)
  • .svgファイルを.pdfに変換するには、オンラインユーティリティを使用してジョブを実行することもできます。 ここに1つの例があります from この答え 。これには、.pdfサイズを簡単に設定できるという利点があります。

参考文献

14
Suragch

まだ更新していない人のために、Xcode 9(iOS 11)に変更がありました。

Cocoa Touchの新機能(WWDC 2017セッション201)(@ 32:55) https://developer.Apple.com/videos/play/wwdc2017/201/

簡単に言うと、アセットカタログには、属性インスペクターに「Preserve Vector Data」という新しいチェックボックスが含まれるようになりました。チェックすると、PDFデータがコンパイルされたバイナリに含まれ、そのサイズが大きくなります。しかし、iOSがベクターデータを両方向にスケーリングし、素敵な画像を提供する機会を与えてくれます(独自の困難を伴います)。 11より下のiOSの場合、回答で上に説明した古いスケーリングメカニズムが使用されます。

7
Dren

プロジェクト内の通常のPDFファイルをベクター画像として使用し、この拡張機能を使用して任意のサイズの画像をレンダリングできます。 iOSはPDFファイルから.PNG画像を生成しないため、この方法の方がはるかに優れています。さらに、任意のサイズで画像をレンダリングできます。

    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
Bruno Paulino