如何区分两个“onpause”事件 - 由单击“暂停”按钮引起,以及由到达媒体片段末尾引起?

Posted

技术标签:

【中文标题】如何区分两个“onpause”事件 - 由单击“暂停”按钮引起,以及由到达媒体片段末尾引起?【英文标题】:How to distinguish between two "onpause" events - caused by clicking “pause” button, and caused by reaching the end of a media fragment? 【发布时间】:2015-07-29 14:59:29 【问题描述】:

如果用户想要停止 html5 媒体,例如通过单击“暂停”本机控制按钮,我们会收到“onpause”事件。 同时,如果媒体元素到达指定片段的末尾,它会自动触发相同的“onpause”事件。是否可以将一个与另一个分开?在 JQuery 风格中,

<video id="video1" src="url/video.webm#t=10,20" controls></video>

<script type="text/javascript">
  $(window).load(function ()  
    $('#video1').on("manualpause", function () 
      alert("you paused this media manually!");
    );
    $('#video1').on("fragmentend", function () 
      alert("you've reached the end of the fragment! your media is now paused automatically!");
    );
  );
</script>

我尝试使用“ontimeupdate”事件,但拒绝了:我想在发生自动暂停(由到达片段末尾引起)时做出准确反应。

【问题讨论】:

developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events 从官方 MDN 文档中,显然有 endedpause 事件。这是你想要的? 结束 播放完成时发送。,而暂停 播放暂停时发送。 问题是到达媒体片段的末尾会触发“onpause”事件(不是“end”),我不明白如何捕捉这样一个特定的自动暂停。两种情况下的事件是相同的,但它的性质(从用户的角度来看)是不同的! 根据文档,ended 在播放完成时抛出,因此它应该在媒体结束时抛出,而暂停事件不应该被调用。您是否 100% 确定正在引发暂停事件? 你可以试试 $("#video1").bind('end', function() ... ? 为什么要说“结束”?片段的结束不是媒体的结束! 不代表播放完成,代表暂停 【参考方案1】:

仅在完整曲目完成后才会发出结束事件。当您播放片段时,它只会在片段结束时暂停曲目,因为曲目本身尚未结束(除非片段的结束时间恰好也是结束)。

一个媒体元素被称为暂停用户交互,当它 paused 属性为 false,readyState 属性为 HAVE_FUTURE_DATA 或 HAVE_ENOUGH_DATA 并且用户代理已达到 媒体资源中的点,用户必须在其中进行选择 要继续的资源。

只有在以下情况下才会发生结束事件:

媒体元素在以下情况下结束播放:

元素的 readyState 属性为 HAVE_METADATA 或更大,并且

要么:

当前播放位置是媒体资源的结尾,并且 播放方向为正向,并且 媒体元素没有指定循环属性,或者媒体元素具有当前媒体控制器。 或: 当前播放位置是最早可能的位置,并且 播放的方向是向后的。

Source

要检测是否由于片段结束而触发了暂停事件,您可以将 currentTime 与片段结束时间进行比较(是的,理论上您也可以在这个时间点按暂停按钮,但这将与音频元素一样接近,除非事件本身具有揭示暂停来源的秘密属性,我不知道)。

由于我们处理的是浮点值,因此您需要使用 epsilon 来比较时间。假设您 parse 或其他方式有办法获取片段的结束时间,您可以这样做:

function onPauseHandler(e) 
    var fragmentEndTime = ...;   // get/parse end-fragment into this var
    if (isEqual(this.currentTime, fragmentEndTime)) 
      // likely that fragment ended
    
    else 
      // a manual pause
    


function isEqual(n1, n2) 
   return Math.abs(n1 - n2) < 0.00001

【讨论】:

谢谢。嗯,这正是我在写“我试图利用 'ontimeupdate' 事件”时的意思,但我不知道……这似乎是一个非常简单的 hack。也许我们需要检查媒体本身是否被点击(点击“暂停”会触发“onclick”吗?)。但如果没有更好的办法,我需要接受这一点...... @lyricallywicked 您可以在某些浏览器中使用detect f.ex. click events(例如,在 FF 中工作,但在 Chrome 中不可用),这使得它不可靠,或者可能更好的是,为控件提供自定义按钮。 实际上4.7.10.8 Playing the media resource 会是一个更好的参考,因为那里写着When the current playback position reaches the end [...], then the user agent must follow these steps:4. [...] and the media element has still ended playback, [...], and paused is false, changes paused to true and fires a simple event named pause at the media element.。我喜欢你的解决方法,因此 +1。【参考方案2】:

今天我在搜索“为什么 onpause 在 onended 发生时也会触发”时出现了这个问题。我想将 onpause 事件和 onend 事件之间的逻辑分开。

这是我的看法:

videoRef.onpause = (e) => 
  if (e.target.currentTime != e.target.duration) 
    // handleOnPause();
  

我同时注册了onpauseonended 处理程序,当onpause 不在视频结尾时运行代码。

【讨论】:

以上是关于如何区分两个“onpause”事件 - 由单击“暂停”按钮引起,以及由到达媒体片段末尾引起?的主要内容,如果未能解决你的问题,请参考以下文章

如何生成 onPause() 事件代码 [关闭]

区分不同类型的 beforeunload 事件

unity 一个物体同时添加单击和双击事件,怎么区分

如何捕获由单击android活动的右上角X引起的事件

Qt:QPushButton 单击双击响应区分

onTouchEvent()中如何区分移动和点击?