【问题标题】:Pan Gesture with AVPlayer使用 AVPlayer 平移手势
【发布时间】:2016-11-01 15:34:30
【问题描述】:

此功能对我的应用程序非常重要,并且非常希望得到一些帮助。基本上,我想在视频播放器中添加一个UIPanGestureRecognizer,以便用户可以通过手势快进/快退视频。

Apple 有一些使用 Swift 3 的示例代码,并且已经创建了整个视频播放器。唯一缺少的是UIPanGestureRecognizer。这是链接:https://developer.apple.com/library/content/samplecode/AVFoundationSimplePlayer-iOS/Introduction/Intro.html#//apple_ref/doc/uid/TP40016103

viewWillAppear 我添加了这样的手势:

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture))
view.addGestureRecognizer(panGesture)

这是有些工作的代码。目前正在刷机。

问题是每次我开始平移手势时,视频都会跳到中间,我从那里开始。平移手势不是从视频当前所在的位置快进/快退,而是将视频跳过到中间,然后允许我快进/快退,这不好。

func handlePanGesture(sender: UIPanGestureRecognizer) {
    switch sender.state {
    case .began, .changed:
        let translation = sender.translation(in: self.view)
        var horizontalTranslation = Float(translation.x)

        let durationInSeconds = Float(CMTimeGetSeconds(player.currentItem!.asset.duration))

        // Using 275 as the limit for delta along x
        let translationLimit: Float = 275
        let minTranslation: Float = -1 * translationLimit
        let maxTranslation: Float = translationLimit

        if horizontalTranslation > maxTranslation {
            horizontalTranslation = maxTranslation
        }

        if horizontalTranslation < minTranslation {
            horizontalTranslation = minTranslation
        }

        let timeToSeekTo = normalize(delta: horizontalTranslation , minDelta: minTranslation, maxDelta: maxTranslation, minDuration: 0, maxDuration: durationInSeconds)
        print("horizontal translation \(horizontalTranslation) \n timeToSeekTo: \(timeToSeekTo)")

        let cmTime = CMTimeMakeWithSeconds(Float64(timeToSeekTo), self.player.currentTime().timescale)
        player.seek(to: cmTime)

    default:
        print("default")
    }

}

func normalize(delta: Float, minDelta: Float, maxDelta: Float, minDuration: Float, maxDuration: Float) -> Float {

    let result = ((delta - minDelta) * (maxDuration - minDuration) / (maxDelta - minDelta) + minDuration)
    return result
}

任何帮助都会很棒 - 谢谢!

【问题讨论】:

    标签: ios avfoundation normalization avplayer seek


    【解决方案1】:

    感谢您的代码。我用过,改了几行,效果很好。

       @objc func handlePanGesture(sender: UIPanGestureRecognizer) {
          switch sender.state {
           case .began, .changed:
            let translation = sender.translation(in: self.view)
            let horizontalTranslation = Float(translation.x)
    
            let durationInSeconds = Float(CMTimeGetSeconds(player.currentItem!.asset.duration))
    
            // normalize based on duration and width of the view
            let scale:Float = durationInSeconds / Float(self.view.frame.width) / 4
            // then you need to add the current time of player to avoid it starting from the middle.            
            let seekTime = horizontalTranslation * scale + Float((self.player.currentItem?.currentTime().seconds)!)
    
            let cmTime = CMTimeMakeWithSeconds(Float64(Float(seekTime)), preferredTimescale: self.player.currentTime().timescale)
            player.seek(to: cmTime)
            print("horizontal translation \(horizontalTranslation) \n timeToSeekTo: \(seekTime)")
    
        default:
            print("default")
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      我已经用AVPlayer 实现了UIPanGesture,下面是我的工作代码[swift 3]

      func handleDraging(_ gesture:UIPanGestureRecognizer){
              let location = gesture.location(in: self.playerView)
              if gesture.state == .began {
                  print("\n\n-->---> Panning.state = .began at Point.x = \(location.x)")
                  self.playerLayer.player?.rate = 0
                  self.stopTimer()
              }else if gesture.state == .changed {
                  let valocity = gesture.velocity(in: self.playerView)
                  print("\n\n-->---> Panning.state = .changed at Point.x = \(location.x)")
                  let percentage = Double(location.x) / Double(self.playerView.frame.width)
                  let currentTime = self.playerLayer.player!.currentTime()
                  let currentSeconds = CMTimeGetSeconds(currentTime)
                  var newSeconds = currentSeconds + percentage
                  if valocity.x < 0 {
                      newSeconds = currentSeconds - percentage
                  }
                  let newTime = CMTime(seconds: newSeconds, preferredTimescale: self.playerLayer.player!.currentTime().timescale)
                  self.playerLayer.player?.seek(to: newTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
                  let total = CGFloat(CMTimeGetSeconds(self.playerLayer.player!.currentItem!.asset.duration))
                  let seconds = CGFloat(CMTimeGetSeconds(newTime))
                  self.interval = Double(seconds)//here update your CurrentTimelabel.text .....
      
                  let temp = seconds/total
                  self.progress = Float(temp)//here update your UIProgressBar.progress .....
                  print("\n\t-->Total Progress = \(temp)")
              }else if gesture.state == .ended || gesture.state == .failed || gesture.state == .recognized {
                  gesture.setTranslation(CGPoint.zero, in: self.playerView)
                  self.startTimer()
                  self.playerLayer.player?.playImmediately(atRate: 1)
              }
          }
      

      【讨论】:

      • 你有stopTimer()、startTimer()等调用。它们在哪里定义?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多