         return convert(imageView?.frame ?? .zero, from: imageView?.superview)
     }
 
+    /**
+     *  重置图片或视频的大小，使用的场景例如：相册控件里放大当前图片、划到下一张、再回来，当前的图片或视频应该恢复到原来大小。
+     *  注意子类重写需要调一下super。
+     */
+    public func revertZooming() {
+        
+    }
+
+    public let emptyView = QMUIEmptyView()
+    
+    /**
+     *  显示一个 loading
+     *  @info 注意 cell 复用可能导致当前页面显示一张错误的旧图片/视频，所以一般情况下需要视情况同时将 image/livePhoto/videoPlayerItem 等属性置为 nil 以清除图片/视频的显示
+     */
+    public func showLoading() {
+    }
+    
+    /**
+     *  显示一句提示语
+     *  @info 注意 cell 复用可能导致当前页面显示一张错误的旧图片/视频，所以一般情况下需要视情况同时将 image/livePhoto/videoPlayerItem 等属性置为 nil 以清除图片/视频的显示
+     */
+    public func showEmptyView(with text: String) {
+    
+    }
+    
+    /**
+     *  将 emptyView 隐藏
+     */
+    public func hideEmptyView() {
+    }
+    
+    override func didMoveToWindow() {
+        // 当 self.window 为 nil 时说明此 view 被移出了可视区域（比如所在的 controller 被 pop 了），此时应该停止视频播放
+        if window == nil {
+            endPlayingVideo()
+        }
+    }
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        
+        
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
     private var currentContentView: UIView? {
         //        if (_imageView) {
-        //            return _imageView;
+        //            return _imageView
         //        }
         //        if (_livePhotoView) {
-        //            return _livePhotoView;
+        //            return _livePhotoView
         //        }
         //        if (self.videoPlayerView) {
-        //            return self.videoPlayerView;
+        //            return self.videoPlayerView
         //        }
         return nil
     }
 }
 
 class QMUIZoomImageViewVideoToolbar: UIView {
+    public let playButton = QMUIButton()
+    public let pauseButton = QMUIButton()
+    public let slider = QMUISlider()
+    public let sliderLeftLabel = UILabel()
+    public let sliderRightLabel = UILabel()
+
     // 可通过调整此属性来调整 toolbar 的视觉位置，默认为 {25, 25, 25, 18}
     // 如果同时实现了 QMUIZoomImageViewDelegate 的 contentInsetsForVideoToolbar:inZoomingImageView: 方法，则此处设置的值会覆盖掉 delegate 中返回的值
     public var contentInsets = UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 18)
-}
+
+    // 可通过这些属性修改 video 播放时屏幕底部工具栏的播放/暂停图标
+    public var playButtonImage = QMUIZoomImageViewImageGenerator.smallPlayImage
+    public var pauseButtonImage = QMUIZoomImageViewImageGenerator.pauseImage
+}
+
+class QMUIZoomImageViewImageGenerator {
+    
+    private static let iconsColor = UIColor(r: 0, g: 0, b: 0, a: 0.25)
+    
+    static var largePlayImage: UIImage? {
+        let width: CGFloat = 60
+        
+        UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: width), false, 0)
+        guard let context = UIGraphicsGetCurrentContext() else {
+            return nil
+        }
+
+        context.setStrokeColor(UIColor(r: 255, g: 255, b: 255, a: 0.75).cgColor)
+
+        // circle outside
+        context.setFillColor(iconsColor.cgColor)
+        let circleLineWidth: CGFloat = 1
+        // consider line width to avoid edge clip
+        let circle = UIBezierPath(ovalIn: CGRect(x: circleLineWidth / 2,
+                                                 y: circleLineWidth / 2,
+                                                 width: width - circleLineWidth,
+                                                 height: width - circleLineWidth))
+        circle.lineWidth = circleLineWidth
+        circle.stroke()
+        circle.fill()
+        
+        // triangle inside
+        context.setFillColor(iconsColor.cgColor)
+        let triangleLength: CGFloat = width / 2.5
+        let triangle = trianglePath(with: triangleLength)
+        let offset = UIOffset(horizontal: width / 2 - triangleLength * tan(.pi / 6) / 2, vertical: width / 2 - triangleLength / 2)
+        triangle.apply(CGAffineTransform(translationX: offset.horizontal, y: offset.vertical))
+        triangle.fill()
+
+        let image = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return image
+    }
+    
+    // @param length of the triangle side
+    private static func trianglePath(with length: CGFloat) -> UIBezierPath {
+        let path = UIBezierPath()
+        path.move(to: .zero)
+        path.addLine(to: CGPoint(x: length * cos(.pi / 6), y: length / 2))
+        path.addLine(to: CGPoint(x: 0, y: length))
+        path.close()
+        return path
+    }
+
+    static var smallPlayImage: UIImage? {
+        // width and height are equal
+        let width: CGFloat = 17
+        
+        UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: width), false, 0)
+        guard let context = UIGraphicsGetCurrentContext() else {
+            return nil
+        }
+
+        context.setFillColor(iconsColor.cgColor)
+        let path = trianglePath(with: width)
+        path.fill()
+
+        let image = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return image
+    }
+
+    static var pauseImage: UIImage? {
+        let size = CGSize(width: 12, height: 18)
+        
+        UIGraphicsBeginImageContextWithOptions(size, false, 0)
+        guard let context = UIGraphicsGetCurrentContext() else {
+            return nil
+        }
+
+        context.setStrokeColor(iconsColor.cgColor)
+        let lineWidth: CGFloat = 2
+        let path = UIBezierPath()
+        path.move(to: CGPoint(x: lineWidth / 2, y: 0))
+        path.addLine(to: CGPoint(x: lineWidth / 2, y: size.height))
+        path.move(to: CGPoint(x: size.width - lineWidth / 2, y: 0))
+        path.addLine(to: CGPoint(x: size.width - lineWidth / 2, y: size.height))
+        path.lineWidth = lineWidth
+        path.stroke()
+
+        let image = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return image
+    }
+}

//

import Photos

protocol QMUIZoomImageViewDelegate: class {
    func singleTouch(in zoomingImageView: QMUIZoomImageView, location: CGPoint)

            livePhotoStorge = newValue
        }
    }
    
    /// 用于显示 Live Photo 的 view，仅在 iOS 9.1 及以后才有效
    @available(iOS 9.1, *)
    public var livePhotoView: PHLivePhotoView {
        return
    }
    
    /// 设置当前要显示的 video ，会把 image/livePhoto 相关内容清空，因此注意不要直接通过 videoPlayerLayer 来设置
    public weak var videoPlayerItem: AVPlayerItem?
    
    /// 用于显示 video 的 layer
    public weak var videoPlayerLayer: AVPlayerLayer {
        return
    }
    
    // 播放 video 时底部的工具栏，你可通过此属性来拿到并修改上面的播放/暂停按钮、进度条、Label 等的样式
    // @see QMUIZoomImageViewVideoToolbar
    public weak var videoToolbar: QMUIZoomImageViewVideoToolbar {
        return
    }
    
    // 播放 video 时屏幕中央的播放按钮
    public var videoCenteredPlayButton: QMUIButton {
        return
    }
    
    // 可通过此属性修改 video 播放时屏幕中央的播放按钮图片
    public var videoCenteredPlayButtonImage: UIImage?
    
    /// 暂停视频播放
    public func pauseVideo() {
        
    }

    /// 停止视频播放，将播放状态重置到初始状态
    public func endPlayingVideo() {
        
    }
    
    /**
     *  获取当前正在显示的图片/视频在整个 QMUIZoomImageView 坐标系里的 rect（会按照当前的缩放状态来计算）
     */
