我在 iPhone 6s 上 的 3D Touch 实验 继续 ForceZoom ,这是一个扩展的 UIImageView ,它显示大图像上触摸点的 1:1 细节视图。
演示(上图)包含三个大图像, 森林 (1600 x 1200)、 药房 (4535 x 1823) 和 petronas (3264 x 4896)。对图像的初始触摸会显示触摸位置周围的预览框,然后深按会弹出该点全分辨率图像的方形预览。分辨率越高,预览框越小。
安装与实施
ForceZoom 包含两个需要复制到宿主应用程序项目中的文件:
要在应用程序中实现 ForceZoom 组件,请使用默认图像和视图控制器实例化并添加到视图中:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
显示预览帧
由于弹出预览将是屏幕上可以容纳的最大正方形:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
白色预览框是一个 CAShapeLayer,它的大小需要与图像在屏幕上的缩放比例相同。执行此操作的数学是在 touchesBegan 调用的 displayPreviewFrame() 方法中:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
其中 imageScale 只是组件的宽度或高度除以图像的宽度或高度:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
启动 Peek 预览
当调用 previewingContext(viewControllerForLocation) 以响应用户的深压时, ForceZoom 需要将触摸的规范化位置传递给预览组件。这是因为我使用弹出图像视图层的 contentsRect 来定位和裁剪全分辨率图像,而 contentsRect 使用标准化图像坐标。
在 previewingContext(viewControllerForLocation) 中有几个步骤可以做到这一点。首先,我将预览帧的大小计算为标准化值。这将用作触摸原点的偏移量以形成剪辑矩形的原点:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
接下来,我计算组件边缘与其包含的图像边缘之间的距离:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
然后,根据触摸点的位置和这两个新值,我可以创建剪辑矩形的标准化 x 原点:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
我对 y 做同样的事情,并用这两个标准化值创建一个预览点:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
...传递给我的 ForceZoomPreview :
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
窥视预览
预览组件现在几乎没有什么工作要做。它在其构造函数(上方)中传递了规范化原点,因此它需要做的就是使用这些值来设置图像视图的 contentsRect:
class ViewController: UIViewController
{
var imageView: ForceZoomWidget!
override func viewDidLoad()
{
super.viewDidLoad()
imageView = ForceZoomWidget(image: UIImage(named: "forest.jpg")!,
viewController: self)
view.addSubview(imageView)
}
}
源代码
一如既往,这个项目的完整源代码可以在 我的 GitHub 存储库 中找到。享受!