如何包装HTML5视频元素'的currentTime属性

How can I wrap the HTML5 video element's currentTime property?

本文关键字:属性 currentTime 元素 视频 何包装 包装 HTML5      更新时间:2023-09-26

我正在开发一个视频播放器,作为学习模块系统的一部分。某些模块要求用户不能(轻易)在视频中跳过。我知道这通常会被认为是一种糟糕的用户体验,但在这种情况下,这是至关重要的。

我已经能够通过执行以下操作来覆盖video.currentTime属性。它可以防止跳过,但我需要能够有条件地打开和关闭它。

Object.defineProperty(videoElement, 'currentTime', {
  enumerable: true,
  configurable: true,
  get: function() {
    // return from original currentTime
  },
  set: function(newValue) {
    // intercept values here
  }
});

如何在getter和setter中引用原始的video.currentTime属性?不幸的是,Object.getOwnPropertyDescriptor(videoElement, 'currentTime');返回undefined

可能有一种更优雅的方法可以做到这一点,但在对象上调用原型的currentTimegetter(在本例中为HTMLMediaElement原型)将获得实际的currentTime。因此,这将阻止设置,但允许获取:

  Object.defineProperty(videoElement, 'currentTime', {
      enumerable: true,
      configurable: true,
      get: function() {
        var ct = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype,
           'currentTime').get.call(this);
        return ct;
      },
      set: function(newValue) {
        // intercept values here
      }
    });

如果禁用查找(跳过)是您想要做的,那么下面是我的解决方案:

var video = document.getElementById('video');
var supposedCurrentTime = 0;
video.addEventListener('timeupdate', function() {
  if (!video.seeking) {
        supposedCurrentTime = video.currentTime;
  }
});
// prevent user from seeking
video.addEventListener('seeking', function() {
  // guard agains infinite recursion:
  // user seeks, seeking is fired, currentTime is modified, seeking is fired, current time is modified, ....
  var delta = video.currentTime - supposedCurrentTime;
  if (Math.abs(delta) > 0.01) {
    console.log("Seeking is disabled");
    video.currentTime = supposedCurrentTime;
  }
});
// delete the following event handler if rewind is not required
video.addEventListener('ended', function() {
  // reset state in order to allow for rewind
    supposedCurrentTime = 0;
});

这段代码只是在查找时将video.currentTime恢复到其最后一个已知值。这有效地取消了搜索过程。没有必要覆盖/包装currentTime。

包装currentTime的问题是,如果用户足够聪明地选择视频元素并设置其currentTime属性,那么用户可能足够聪明地调用:

Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype,
       'currentTime').set.call(videoElement, videoElement.duration);