NCViewerImageContentTransformers.swift 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // ContentTransformers.swift
  3. // Nextcloud
  4. //
  5. // Created by Suraj Thomas K on 7/17/18 Copyright © 2018 Al Tayer Group LLC..
  6. // Modify for Nextcloud by Marino Faggiana on 04/03/2020.
  7. // Copyright © 2019 Marino Faggiana. All rights reserved.
  8. //
  9. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  10. //
  11. // This program is free software: you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published by
  13. // the Free Software Foundation, either version 3 of the License, or
  14. // (at your option) any later version.
  15. //
  16. // This program is distributed in the hope that it will be useful,
  17. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. // GNU General Public License for more details.
  20. //
  21. // You should have received a copy of the GNU General Public License
  22. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. //
  24. /**
  25. Content transformer used for transition between media item views.
  26. - parameter contentView: The content view on which transform corresponding to the position has to be applied.
  27. - parameter position: Current position for the passed content view.
  28. - note:
  29. The trasnform to be applied on the contentView has to be dependent on the position passed.
  30. The position value can be -ve, 0.0 or positive.
  31. Try to visualize content views at -1.0[previous]=>0.0[current]=>1.0[next].
  32. 1. When position is -1.0, the content view should be at the place meant for previous view.
  33. 2. When the position is 0.0, the transform applied on the content view should make it visible full screen at origin.
  34. 3. When position is 1.0, the content view should be at the place meant for next view.
  35. Be mindful of the drawing order, when designing new transitions.
  36. */
  37. public typealias NCViewerImageContentTransformer = (_ contentView: UIView, _ position: CGFloat) -> Void
  38. // MARK: - Default Transitions
  39. /// An enumeration to hold default content transformers
  40. public enum NCViewerImageDefaultContentTransformers {
  41. /**
  42. Horizontal move-in-out content transformer.
  43. - Requires:
  44. * GestureDirection: Horizontal
  45. */
  46. public static let horizontalMoveInOut: NCViewerImageContentTransformer = { contentView, position in
  47. let widthIncludingGap = contentView.bounds.size.width + NCViewerImageContentView.interItemSpacing
  48. contentView.transform = CGAffineTransform(translationX: widthIncludingGap * position, y: 0.0)
  49. }
  50. /**
  51. Vertical move-in-out content transformer.
  52. - Requires:
  53. * GestureDirection: Vertical
  54. */
  55. public static let verticalMoveInOut: NCViewerImageContentTransformer = { contentView, position in
  56. let heightIncludingGap = contentView.bounds.size.height + NCViewerImageContentView.interItemSpacing
  57. contentView.transform = CGAffineTransform(translationX: 0.0, y: heightIncludingGap * position)
  58. }
  59. /**
  60. Horizontal slide-out content transformer.
  61. - Requires:
  62. * GestureDirection: Horizontal
  63. * DrawOrder: PreviousToNext
  64. */
  65. public static let horizontalSlideOut: NCViewerImageContentTransformer = { contentView, position in
  66. var scale: CGFloat = 1.0
  67. if position < -0.5 {
  68. scale = 0.9
  69. } else if -0.5...0.0 ~= Double(position) {
  70. scale = 1.0 + (position * 0.2)
  71. }
  72. var transform = CGAffineTransform(scaleX: scale, y: scale)
  73. let widthIncludingGap = contentView.bounds.size.width + NCViewerImageContentView.interItemSpacing
  74. let x = position >= 0.0 ? widthIncludingGap * position : 0.0
  75. transform = transform.translatedBy(x: x, y: 0.0)
  76. contentView.transform = transform
  77. let margin: CGFloat = 0.0000001
  78. contentView.isHidden = ((1.0-margin)...(1.0+margin) ~= abs(position))
  79. }
  80. /**
  81. Vertical slide-out content transformer.
  82. - Requires:
  83. * GestureDirection: Vertical
  84. * DrawOrder: PreviousToNext
  85. */
  86. public static let verticalSlideOut: NCViewerImageContentTransformer = { contentView, position in
  87. var scale: CGFloat = 1.0
  88. if position < -0.5 {
  89. scale = 0.9
  90. } else if -0.5...0.0 ~= Double(position) {
  91. scale = 1.0 + (position * 0.2)
  92. }
  93. var transform = CGAffineTransform(scaleX: scale, y: scale)
  94. let heightIncludingGap = contentView.bounds.size.height + NCViewerImageContentView.interItemSpacing
  95. let y = position >= 0.0 ? heightIncludingGap * position : 0.0
  96. transform = transform.translatedBy(x: 0.0, y: y)
  97. contentView.transform = transform
  98. let margin: CGFloat = 0.0000001
  99. contentView.isHidden = ((1.0-margin)...(1.0+margin) ~= abs(position))
  100. }
  101. /**
  102. Horizontal slide-in content transformer.
  103. - Requires:
  104. * GestureDirection: Horizontal
  105. * DrawOrder: NextToPrevious
  106. */
  107. public static let horizontalSlideIn: NCViewerImageContentTransformer = { contentView, position in
  108. var scale: CGFloat = 1.0
  109. if position > 0.5 {
  110. scale = 0.9
  111. } else if 0.0...0.5 ~= Double(position) {
  112. scale = 1.0 - (position * 0.2)
  113. }
  114. var transform = CGAffineTransform(scaleX: scale, y: scale)
  115. let widthIncludingGap = contentView.bounds.size.width + NCViewerImageContentView.interItemSpacing
  116. let x = position > 0.0 ? 0.0 : widthIncludingGap * position
  117. transform = transform.translatedBy(x: x, y: 0.0)
  118. contentView.transform = transform
  119. let margin: CGFloat = 0.0000001
  120. contentView.isHidden = ((1.0-margin)...(1.0+margin) ~= abs(position))
  121. }
  122. /**
  123. Vertical slide-in content transformer.
  124. - Requires:
  125. * GestureDirection: Vertical
  126. * DrawOrder: NextToPrevious
  127. */
  128. public static let verticalSlideIn: NCViewerImageContentTransformer = { contentView, position in
  129. var scale: CGFloat = 1.0
  130. if position > 0.5 {
  131. scale = 0.9
  132. } else if 0.0...0.5 ~= Double(position) {
  133. scale = 1.0 - (position * 0.2)
  134. }
  135. var transform = CGAffineTransform(scaleX: scale, y: scale)
  136. let heightIncludingGap = contentView.bounds.size.height + NCViewerImageContentView.interItemSpacing
  137. let y = position > 0.0 ? 0.0 : heightIncludingGap * position
  138. transform = transform.translatedBy(x: 0.0, y: y)
  139. contentView.transform = transform
  140. let margin: CGFloat = 0.0000001
  141. contentView.isHidden = ((1.0-margin)...(1.0+margin) ~= abs(position))
  142. }
  143. /**
  144. Horizontal zoom-in-out content transformer.
  145. - Requires:
  146. * GestureDirection: Horizontal
  147. */
  148. public static let horizontalZoomInOut: NCViewerImageContentTransformer = { contentView, position in
  149. let minScale: CGFloat = 0.5
  150. // Scale factor is used to reduce the scale animation speed.
  151. let scaleFactor: CGFloat = 0.5
  152. var scale: CGFloat = CGFloat.maximum(minScale, 1.0 - abs(position * scaleFactor))
  153. // Actual gap will be scaleFactor * 0.5 times of contentView.bounds.size.width.
  154. let actualGap = contentView.bounds.size.width * scaleFactor * 0.5
  155. let gapCorrector = NCViewerImageContentView.interItemSpacing - actualGap
  156. let widthIncludingGap = contentView.bounds.size.width + gapCorrector
  157. let translation = (widthIncludingGap * position)/scale
  158. var transform = CGAffineTransform(scaleX: scale, y: scale)
  159. transform = transform.translatedBy(x: translation, y: 0.0)
  160. contentView.transform = transform
  161. }
  162. /**
  163. Vertical zoom-in-out content transformer.
  164. - Requires:
  165. * GestureDirection: Vertical
  166. */
  167. public static let verticalZoomInOut: NCViewerImageContentTransformer = { contentView, position in
  168. let minScale: CGFloat = 0.5
  169. // Scale factor is used to reduce the scale animation speed.
  170. let scaleFactor: CGFloat = 0.5
  171. let scale: CGFloat = CGFloat.maximum(minScale, 1.0 - abs(position * scaleFactor))
  172. // Actual gap will be scaleFactor * 0.5 times of contentView.bounds.size.height.
  173. let actualGap = contentView.bounds.size.height * scaleFactor * 0.5
  174. let gapCorrector = NCViewerImageContentView.interItemSpacing - actualGap
  175. let heightIncludingGap = contentView.bounds.size.height + gapCorrector
  176. let translation = (heightIncludingGap * position)/scale
  177. var transform = CGAffineTransform(scaleX: scale, y: scale)
  178. transform = transform.translatedBy(x: 0.0, y: translation)
  179. contentView.transform = transform
  180. }
  181. }