mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Animate the transition to full screen image view
This commit is contained in:
@@ -43,6 +43,7 @@ class ArticleViewController: UIViewController {
|
||||
}()
|
||||
|
||||
private var webView: WKWebView!
|
||||
private var transition = ImageTransition()
|
||||
|
||||
weak var coordinator: SceneCoordinator!
|
||||
|
||||
@@ -65,6 +66,9 @@ class ArticleViewController: UIViewController {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var clickedImage: UIImage?
|
||||
var clickedImageFrame: CGRect?
|
||||
|
||||
var articleExtractorButtonState: ArticleExtractorButtonState {
|
||||
get {
|
||||
@@ -357,17 +361,43 @@ extension ArticleViewController: WKScriptMessageHandler {
|
||||
|
||||
let base64Image = String(clickMessage.imageURL.suffix(from: range.upperBound))
|
||||
if let imageData = Data(base64Encoded: base64Image), let image = UIImage(data: imageData) {
|
||||
|
||||
let rect = CGRect(x: CGFloat(clickMessage.x), y: CGFloat(clickMessage.y), width: CGFloat(clickMessage.width), height: CGFloat(clickMessage.height))
|
||||
clickedImageFrame = webView.convert(rect, to: nil)
|
||||
clickedImage = image
|
||||
|
||||
let imageVC = UIStoryboard.main.instantiateController(ofType: ImageViewController.self)
|
||||
imageVC.image = image
|
||||
imageVC.modalPresentationStyle = .fullScreen
|
||||
imageVC.transitioningDelegate = self
|
||||
present(imageVC, animated: true)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: UIViewControllerTransitioningDelegate
|
||||
|
||||
extension ArticleViewController: UIViewControllerTransitioningDelegate {
|
||||
|
||||
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
guard let frame = clickedImageFrame, let image = clickedImage else { return nil }
|
||||
transition.originFrame = frame
|
||||
transition.originImage = image
|
||||
transition.presenting = true
|
||||
return transition
|
||||
}
|
||||
|
||||
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
transition.presenting = false
|
||||
return transition
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: JSON
|
||||
|
||||
private struct TemplateData: Codable {
|
||||
let style: String
|
||||
let body: String
|
||||
|
||||
@@ -42,6 +42,10 @@ open class ImageScrollView: UIScrollView {
|
||||
private var scaleToRestoreAfterResize: CGFloat = 1.0
|
||||
var maxScaleFromMinScale: CGFloat = 3.0
|
||||
|
||||
var zoomedFrame: CGRect {
|
||||
return convert(zoomView?.frame ?? CGRect.zero, to: nil)
|
||||
}
|
||||
|
||||
override open var frame: CGRect {
|
||||
willSet {
|
||||
if frame.equalTo(newValue) == false && newValue.equalTo(CGRect.zero) == false && imageSize.equalTo(CGSize.zero) == false {
|
||||
@@ -93,16 +97,14 @@ open class ImageScrollView: UIScrollView {
|
||||
// center horizontally
|
||||
if frameToCenter.size.width < bounds.width {
|
||||
frameToCenter.origin.x = (bounds.width - frameToCenter.size.width) / 2
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
frameToCenter.origin.x = 0
|
||||
}
|
||||
|
||||
// center vertically
|
||||
if frameToCenter.size.height < bounds.height {
|
||||
frameToCenter.origin.y = (bounds.height - frameToCenter.size.height) / 2
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
frameToCenter.origin.y = 0
|
||||
}
|
||||
|
||||
@@ -260,8 +262,7 @@ open class ImageScrollView: UIScrollView {
|
||||
// zoom out if it bigger than middle scale point. Else, zoom in
|
||||
if zoomScale >= maximumZoomScale / 2.0 {
|
||||
setZoomScale(minimumZoomScale, animated: true)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let center = gestureRecognizer.location(in: gestureRecognizer.view)
|
||||
let zoomRect = zoomRectForScale(ImageScrollView.kZoomInFactorFromMinWhenDoubleTap * minimumZoomScale, center: center)
|
||||
zoom(to: zoomRect, animated: true)
|
||||
|
||||
66
iOS/Article/ImageTransition.swift
Normal file
66
iOS/Article/ImageTransition.swift
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// ImageAnimator.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 10/15/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ImageTransition: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
|
||||
let duration = 0.5
|
||||
var presenting = true
|
||||
var originFrame: CGRect!
|
||||
var originImage: UIImage!
|
||||
|
||||
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||
return duration
|
||||
}
|
||||
|
||||
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||
|
||||
let destFrame: CGRect = {
|
||||
if presenting {
|
||||
let imageController = transitionContext.viewController(forKey: .to) as! ImageViewController
|
||||
return imageController.zoomedFrame
|
||||
} else {
|
||||
let imageController = transitionContext.viewController(forKey: .from) as! ImageViewController
|
||||
return imageController.zoomedFrame
|
||||
}
|
||||
}()
|
||||
|
||||
let initialFrame = presenting ? originFrame! : destFrame
|
||||
let targetFrame = presenting ? destFrame : originFrame!
|
||||
|
||||
let imageView = UIImageView(image: originImage)
|
||||
imageView.frame = initialFrame
|
||||
|
||||
// let xScaleFactor = presenting ? initialFrame.width / targetFrame.width : targetFrame.width / initialFrame.width
|
||||
// let yScaleFactor = presenting ? initialFrame.height / targetFrame.height : targetFrame.height / initialFrame.height
|
||||
// let scaleTransform = CGAffineTransform(scaleX: xScaleFactor, y: yScaleFactor)
|
||||
|
||||
let fromView = transitionContext.view(forKey: .from)!
|
||||
fromView.removeFromSuperview()
|
||||
|
||||
transitionContext.containerView.backgroundColor = UIColor.systemBackground
|
||||
transitionContext.containerView.addSubview(imageView)
|
||||
|
||||
UIView.animate(
|
||||
withDuration: duration,
|
||||
animations: {
|
||||
imageView.frame = targetFrame
|
||||
// imageView.transform = scaleTransform
|
||||
// imageView.center = CGPoint(x: targetFrame.midX, y: targetFrame.midY)
|
||||
}, completion: { _ in
|
||||
imageView.removeFromSuperview()
|
||||
let toView = transitionContext.view(forKey: .to)!
|
||||
transitionContext.containerView.addSubview(toView)
|
||||
transitionContext.containerView.bringSubviewToFront(toView)
|
||||
transitionContext.completeTransition(true)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,9 @@ class ImageViewController: UIViewController {
|
||||
@IBOutlet weak var imageScrollView: ImageScrollView!
|
||||
|
||||
var image: UIImage!
|
||||
var zoomedFrame: CGRect {
|
||||
return imageScrollView.zoomedFrame
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
Reference in New Issue
Block a user