Мои эксперименты с 3D Touch на iPhone 6s продолжаются с 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)
}
}
Отображение рамки предварительного просмотра
Так как во всплывающем превью будет самый большой квадрат, который может поместиться на экране:
var peekPreviewSize: CGFloat
{
return min(UIScreen.mainScreen().bounds.size.width,
UIScreen.mainScreen().bounds.size.height)
}
Белое окно предварительного просмотра, которое является CAShapeLayer, должно быть такого размера в том же масштабе, что и изображение, масштабированное на экране. Математика для этого находится в методе displayPreviewFrame (), который вызывается touchesBegan:
let previewFrameSize = peekPreviewSize * imageScale
Где imageScale — это просто ширина или высота компонента, деленная на ширину или высоту изображения:
var imageScale: CGFloat
{
return min(bounds.size.width / image!.size.width, bounds.size.height / image!.size.height)
}
Запуск предварительного просмотра
Когда previewingContext (viewControllerForLocation) вызывается в ответ на глубокое нажатие пользователя, ForceZoom должен передать компоненту предварительного просмотра нормализованную позицию касания. Это связано с тем, что я использую объект contentRect всплывающего изображения для позиционирования и обрезки изображения с полным разрешением, а contentRect использует нормализованные координаты изображения.
Есть несколько шагов в previewingContext (viewControllerForLocation), чтобы сделать это. Прежде всего, я вычисляю размер рамки предварительного просмотра как нормализованное значение. Это будет использоваться как смещение от источника касания для формирования источника прямоугольника клипа:
let offset = ((peekPreviewSize * imageScale) / (imageWidth * imageScale)) / 2
Затем я вычисляю расстояние между краем компонента и краем изображения, которое он содержит:
let leftBorder = (bounds.width - (imageWidth * imageScale)) / 2
Затем, с расположением точки касания , и эти два новых значений, я могу создать нормализованное х происхождение клипа прямоугольника:
let normalisedXPosition = ((location.x - leftBorder) / (imageWidth * imageScale)) - offset
Я делаю то же самое для y и с этими двумя нормализованными значениями создаю точку предварительного просмотра:
let topBorder = (bounds.height - (imageHeight * imageScale)) / 2
let normalisedYPosition = ((location.y - topBorder) / (imageHeight * imageScale)) - offset
let normalisedPreviewPoint = CGPoint(x: normalisedXPosition, y: normalisedYPosition)
… который передается в мой ForceZoomPreview :
let peek = ForceZoomPreview(normalisedPreviewPoint: normalisedPreviewPoint, image: image!)
The Peek Preview
У компонента предварительного просмотра теперь очень мало работы. Он передал нормализованный источник в своем конструкторе (выше), поэтому все, что ему нужно сделать, это использовать эти значения для установки contentRect представления изображения:
imageView.layer.contentsRect = CGRect(
x: max(min(normalisedPreviewPoint.x, 1), 0),
y: max(min(normalisedPreviewPoint.y, 1), 0),
width: view.frame.width / image.size.width,
height: view.frame.height / image.size.height)
Исходный код
Как всегда, полный исходный код этого проекта доступен в моем репозитории GitHub здесь . Наслаждайтесь!