6

我有一个带有隐藏<audio>对象的页面,该页面正在通过 javascript 使用自定义按钮启动和停止。(原因是我想自定义按钮,而绘制音频播放器似乎会破坏 iPad 上的渲染性能)。一个简化的例子(在咖啡脚本中):

// Works fine on all browsers

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play          // Bind button's click event with jQuery

_play: (e) =>
  @_audio[0].play()                    // Call play() on audio element

当从绑定到事件的函数触发时,音频播放正常,但我实际上希望在click文件播放之前完成动画,所以我把. 但是我无法让它工作:.play()setTimeout

// Will not play on iPad

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play          // Bind button's click event with jQuery

_play: (e) =>
  setTimeout (=>                       // Declare a 300ms timeout
    @_audio[0].play()                  // Call play() on audio element
  ), 300

我检查了@_audio( this._audio) 是否在范围内,并且它的play()方法存在。为什么这在 iPad 上不起作用?

编辑:碰巧,上面的简化测试用例确实有效。请参阅下面的@apsillers 的回答和我对此的评论。

4

3 回答 3

13

请参阅Apple 的 iOS 注意事项指南

...在用户开始播放之前,JavaScriptplay()load()方法也处于非活动状态,除非play()orload()方法由用户操作触发。换句话说,用户启动的播放按钮有效,但onLoad="play()"事件无效。

您的setTimeout()回调似乎不符合用户启动的操作,尽管它setTimeout()本身是在用户启动的函数中。

建议:我没有要测试的 iOS 设备,但也许在用户按下按钮时进行初始播放/暂停会解除此限制。也就是说,您调用play()然后立即暂停它,然后调用 animate 和调用的setTimeout()函数play()。这使得用户启动的功能让 iOS 知道以后可以加载和播放这个视频。

于 2012-06-11T16:13:50.937 回答
1

有些设备您无法自动调用播放音频系统您是否尝试过使用按钮并单击播放,看看是否有效,如果有效,它如何工作它是否打开音频播放器来播放它,如果是这样,您不允许自动播放媒体如果我没记错的话与视频标签相同

我认为 safari 会检查触发音频的事件因此为什么点击有效

于 2012-06-11T16:11:56.170 回答
1

@apsillers 在他的回答中建议我可以重新排列我的代码以满足 iPad 的“用户启动的操作”要求。我做了一些挖掘,事实证明这是真的。

要求似乎是play()调用只能在一个 setTimeout范围内(因此,我在原始问题中给出的简化示例确实有效——我最初有play()几个setTimeouts 深度)。

所以这起作用:

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play

_play: (e) =>
  setTimeout (=>
    @_audio[0].play()                  // play() is only inside one setTimeout
  ), 300

这也可以:

constructor: (@_button, @_audio) ->
  @_button.on 'click', =>
    setTimeout ((e) =>
      @_play(e)
    ), 300

_play: (e) =>
  @_audio[0].play()                    // Still only inside one setTimeout

但这不起作用:

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play

_play: (e) =>
  setTimeout (=>
    // Something useful
    setTimeout (=>
      @_audio[0].play()                // play() is inside two setTimeouts
    ), 300
  ), 300

这也不会(我的原始设置):

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play

_play: (e) =>

  @_button
    .animate { prop: value }, 300, =>

      setTimeout (=>
        @_audio[0].play()              // play() still 'too deep'
      ), 300

在最后一个示例中,似乎 jQuery 的动画回调是从setTimeout库的另一个内部调用的,因此play()再次“太深”。

于 2012-06-11T17:08:02.563 回答