Table of Contents
Quartzフレームワーク の IKImageView に表示した画像の一部を拡大表示し、その表示位置をスクロールできるようにする方法です。
IKImageViewについて
NSImageView に似ていますが、これと異なる点は、表示した画像のズーム(拡大縮小)や回転などを始めとした編集機能を持つことです。画像編集アプリを作成する際に便利な機能があらかじめ組み込まれた便利なクラスとなっています。
以下では、この IKImageView に NSScrollView を組み合わせて、Mac標準アプリの「プレビュー.app」に似た画像の拡大表示ができるサンプルを紹介します。
サンプルのソースコード
プロジェクトを新規作成して、ウィンドウの contentViewController となるクラスを作成します。ここでは MainViewController と名付けます。
MainViewController.swift
import Cocoa import Quartz extension NSSize { static func *(rect: NSSize, ratio: CGFloat) -> NSSize { return NSSize(width: rect.width * ratio, height: rect.height * ratio) } } class MainViewController : NSViewController { var prevMagnification: CGFloat = 1 override func loadView() { // IKImageView の設定 let imageView = IKImageView() // NSScrollView 内の領域 let scrollContentView = NSClipView() scrollContentView.documentView = imageView // NSScrollView の本体 let scrollView = NSScrollView(frame: NSRect(x: 0, y: 0, width: 600, height: 400)) scrollView.contentView = scrollContentView scrollView.hasVerticalScroller = true scrollView.hasHorizontalScroller = true scrollView.autohidesScrollers = false // サイズを調節 imageView.frame = scrollView.frame // 初期の画像 imageView.setImageWith(URL(fileURLWithPath: "読み込む画像のURL")) // ドラッグ&ドロップで画像を読み込む設定 imageView.supportsDragAndDrop = true imageView.backgroundColor = NSColor.green // カスタムのズーム機能を設定 imageView.addGestureRecognizer(NSMagnificationGestureRecognizer(target: self, action: #selector(self.magnificationGesture))) // NSScrollView をウィンドウの contentView とする self.view = scrollView } // ピンチジェスチャの設定 @objc func magnificationGesture(_ gesture: NSMagnificationGestureRecognizer) { let imageView = gesture.view as! IKImageView // 前のズーム値を初期化 if abs(gesture.magnification) < 0.01 { prevMagnification = 0 } // ズームの変化量 let delta: CGFloat = gesture.magnification - prevMagnification imageView.zoomFactor += delta // ズームした画像の大きさに合わせてIKImageViewのサイズを変化させる let currentImageSize = imageView.imageSize() * imageView.zoomFactor let currentRect = NSRect(origin: self.view.frame.origin, size: currentImageSize) if !self.view.frame.contains(currentRect) { // IKImageViewのサイズはウィンドウより小さくならないように imageView.frame.size = currentImageSize } else { imageView.frame = self.view.frame } prevMagnification = gesture.magnification } }
このクラスを AppDelegate で contentViewController に指定します。
AppDelegate.swift
@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { @IBOutlet weak var window: NSWindow! let mainViewController = MainViewController() func applicationDidFinishLaunching(_ aNotification: Notification) { window.delegate = self window.contentViewController = mainViewController } ...
これで、冒頭のサンプルのように拡大縮小表示ができるアプリができます。IKImageView には画像を拡大した際にスクロールバーを表示して全体を見回せるようにする機能はないため NSScrollView を組み合わせてこれを実装しています。
フラグ supportsDragAndDrop を有効にすると、ドラッグ&ドロップで簡単に画像を読み込むことができます。
以上、 IKImageViewによる画像のズームと表示位置のスクロールを行うサンプルの解説でした。