BFVideoThumbProgressView.swift 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //
  2. // BFVideoThumbProgressView.swift
  3. // BFRecordScreenKit
  4. //
  5. // Created by 胡志强 on 2021/12/3.
  6. //
  7. import AVFoundation
  8. import BFCommonKit
  9. import BFUIKit
  10. import Foundation
  11. import SnapKit
  12. import UIKit
  13. class BFVideoThumbProgressView: UIView {
  14. var recordItem: BFRecordItemModel? {
  15. didSet {
  16. if recordItem?.mediaType == .VIDEO {
  17. dealWithVideoThub()
  18. } else if recordItem?.mediaType == .IMAGE {
  19. dealWithImageThub()
  20. }
  21. }
  22. }
  23. var dragScrollProgressHandle: ((Bool, Float) -> Void)?
  24. var dragEndHandle: ((Float) -> Void)?
  25. var dragStartHandle: (() -> Void)?
  26. var isDrag = false
  27. let thumbImageWidth = 70.0
  28. let fetchThumbStrategy: BFVideoThumbProgressStrategyProtocol = BFVideoThumbProgressStrategy()
  29. var progress: Double = 0 {
  30. didSet {
  31. if let second = recordItem?.videoAsset?.duration.seconds, second > 0 {
  32. let w = progressView.contentSize.width - width
  33. progressView.contentOffset = CGPoint(x: progress * Double(w) / second, y: 0)
  34. }
  35. }
  36. }
  37. var thumbImgs = [UIImage]()
  38. lazy var progressView: BFAutolayoutScrollView = {
  39. let sv = BFAutolayoutScrollView()
  40. sv.bounces = false
  41. // sv.backgroundColor = .clear
  42. // sv.backgroundColor = UIColor.hexColor(hexadecimal: "#888888",alpha:0.3)
  43. sv.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.3)
  44. sv.decelerationRate = .fast
  45. sv.showsHorizontalScrollIndicator = false
  46. sv.delegate = self
  47. return sv
  48. }()
  49. lazy var progessIndicateBackV: UIView = {
  50. let vv = UIView()
  51. return vv
  52. }()
  53. // MARK: - 生命周期
  54. override init(frame: CGRect) {
  55. super.init(frame: frame)
  56. addSubview(progressView)
  57. let line = UIView()
  58. line.backgroundColor = .white
  59. line.layer.borderColor = UIColor.black.cgColor
  60. line.layer.borderWidth = 0.3
  61. line.layer.cornerRadius = 1.5
  62. addSubview(line)
  63. line.snp.makeConstraints { make in
  64. make.width.equalTo(3)
  65. make.center.height.equalToSuperview()
  66. }
  67. }
  68. required init?(coder _: NSCoder) {
  69. fatalError("init(coder:) has not been implemented")
  70. }
  71. override func layoutSubviews() {
  72. super.layoutSubviews()
  73. progressView.snp.makeConstraints { make in
  74. make.edges.equalToSuperview()
  75. }
  76. }
  77. func dealWithVideoThub() {
  78. guard let videoAsset = recordItem?.videoAsset else {
  79. return
  80. }
  81. let dur = videoAsset.duration.seconds
  82. if dur > 0 {
  83. let fps = Double(fetchThumbStrategy.frameNumberOfVideo(assetDuration: dur)) / dur
  84. splitVideoFileUrlFps(urlAsset: videoAsset, fps: fps) { [weak self] images in
  85. self?.addThubImages(images: images)
  86. }
  87. }
  88. }
  89. func dealWithImageThub() {
  90. guard let image = recordItem?.coverImg else {
  91. return
  92. }
  93. addThubImages(images: Array(repeating: image, count: 3))
  94. }
  95. func addThubImages(images: [UIImage]) {
  96. if images.count > 0 {
  97. thumbImgs = images
  98. DispatchQueue.main.async { [weak self] in
  99. self?.progressView.contentView.subviews.forEach { subview in
  100. subview.removeFromSuperview()
  101. }
  102. if let sself = self {
  103. var lastiv = UIImageView()
  104. for (i, img) in images.enumerated() {
  105. let iv = UIImageView(image: img)
  106. iv.contentMode = .scaleAspectFill
  107. iv.clipsToBounds = true
  108. sself.progressView.contentView.addSubview(iv)
  109. iv.snp.makeConstraints { make in
  110. make.left.equalTo(CGFloat(i) * CGFloat(sself.thumbImageWidth) + sself.width * 0.5)
  111. make.top.bottom.equalToSuperview()
  112. make.height.equalTo(50)
  113. make.width.equalTo(sself.thumbImageWidth)
  114. }
  115. lastiv = iv
  116. }
  117. lastiv.snp.makeConstraints { make in
  118. make.right.equalTo(sself.width * -0.5)
  119. }
  120. sself.progressView.contentView.addSubview(sself.progessIndicateBackV)
  121. sself.progessIndicateBackV.snp.makeConstraints { make in
  122. make.left.equalTo(sself.width * 0.5)
  123. make.right.equalTo(sself.width * -0.5)
  124. make.bottom.equalToSuperview()
  125. make.height.equalTo(6)
  126. }
  127. }
  128. }
  129. }
  130. }
  131. }
  132. extension BFVideoThumbProgressView: UIScrollViewDelegate {
  133. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  134. if isDrag {
  135. let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
  136. dragScrollProgressHandle?(false, Float(dur))
  137. }
  138. }
  139. func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
  140. isDrag = true
  141. let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
  142. dragStartHandle?()
  143. dragScrollProgressHandle?(true, Float(dur))
  144. }
  145. func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
  146. if !decelerate {
  147. let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
  148. isDrag = false
  149. dragEndHandle?(Float(dur))
  150. }
  151. }
  152. func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
  153. let dur = scrollView.contentOffset.x / (scrollView.contentSize.width - width)
  154. isDrag = false
  155. dragEndHandle?(Float(dur))
  156. }
  157. }