隐藏和显示视频播放器控件
上周,我决定着手解决控制栏方面的一些悬而未决的问题,然后就陷入了与播放器更新相关的“兔子洞”。谢天谢地,我现在已经浮出水面,我想写一些关于由此产生的一些更新。。ve thankfully resurfaced now, and figured I。d write about a few of the updates that came from it.
播放器控制栏的一个预期行为是,当用户在观看视频时处于非活动状态时,它会在几秒钟后淡出。以前,我们在video.js中实现这一点是通过一个CSS技巧。当用户的鼠标移出视频播放器区域时,控制栏会被赋予类名vjs-fade-out
。这个类有一个可见性过渡,并额外增加了2秒的延迟。。s control bar is that it will fade out after a couple of seconds when the user is inactive while watching a video. Previously, the way we achieved this with video.js was through a bit of a CSS trick. When the user。s mouse would move out of the video player area, the control bar would be given the classname vjs-fade-out
. This class had a visibility transition with an added 2 second delay.
.vjs-fade-out {
display: block;
visibility: hidden;
opacity: 0;
-webkit-transition: visibility 1.5s, opacity 1.5s;
-moz-transition: visibility 1.5s, opacity 1.5s;
-ms-transition: visibility 1.5s, opacity 1.5s;
-o-transition: visibility 1.5s, opacity 1.5s;
transition: visibility 1.5s, opacity 1.5s;
-webkit-transition-delay: 2s;
-moz-transition-delay: 2s;
-ms-transition-delay: 2s;
-o-transition-delay: 2s;
transition-delay: 2s;
}
当用户的鼠标移回播放器时,该类将被移除,取消任何延迟的淡出效果。这提供了类似于你期望控件淡出效果的工作方式,并且只需几行JavaScript代码即可添加/移除该类。。s mouse moved back over the player, the class would be removed, canceling any delayed fade-out. This provided a similar experience to how you might expect the controls fading to work, and only took a few lines of javascript to add/remove the class.
player.on('mouseout', function() {
controlBar.addClass('vjs-fade-out');
});
player.on('mouseover', function() {
controlBar.removeClass('vjs-fade-out');
});
然而,这种方法存在一些缺点,使得我们有必要放弃它。。s a few drawbacks though that have made it necessary to move away from this approach.
在全屏模式下,控件不会淡出,因为鼠标永远无法移出播放器区域。。t fade out in fullscreen mode because the mouse can never move out of the player area.
移动设备上没有鼠标,因此需要不同的事件和交互来显示/隐藏控件。
除了这些问题,我们还希望任何播放器组件或插件都能挂接到相同的触发器来隐藏控件。像社交分享图标这样的组件应该以与控件相同的方式淡出。
首先添加的是播放器上的userActive
属性,它可以是true
或false
。这样做是将控件隐藏功能抽象化,使其关注我们真正关心的问题:用户当前是否正在与播放器交互,还是仅仅被动地观看视频。这还将控制栏与跟踪用户活动本身解耦,并允许其他组件通过播放器级别的状态更容易地实现与控制栏相同的行为。。re actually concerned with, that is, whether the user is currently interacting with the player or just passively watching the video. This also decouples the control bar from tracking the user activity itself, and allows other components to more easily behave the same way as the control bar, through a player-level state.
实际属性是player.userActive()
,它返回true
或false
。当此值改变时,它会触发播放器上的一个事件。
player.userActive(true);
player.userActive(false);
播放器元素上也会添加vjs-user-active
或vjs-user-inactive
的CSS类名。现在,这个类名被实际用于隐藏和显示控制栏。。s actually used now to hide and show the control bar.
.vjs-default-skin.vjs-user-inactive .vjs-control-bar {
display: block;
visibility: hidden;
opacity: 0;
-webkit-transition: visibility 1.5s, opacity 1.5s;
-moz-transition: visibility 1.5s, opacity 1.5s;
-ms-transition: visibility 1.5s, opacity 1.5s;
-o-transition: visibility 1.5s, opacity 1.5s;
transition: visibility 1.5s, opacity 1.5s;
}
2秒的延迟已从CSS中移除,取而代之的是通过JavaScript超时机制,内置于将userActive状态设置为false的过程。任何时候播放器上发生鼠标事件,此超时都会重置。例如:
var resetDelay, inactivityTimeout;
resetDelay = function() {
clearTimeout(inactivityTimeout);
inactivityTimeout = setTimeout(function() {
player.userActive(false);
}, 2000);
};
player.on('mousemove', function() {
resetDelay();
});
mousemove
事件在鼠标移动时非常频繁地被调用,我们希望在此操作期间尽可能少地占用播放器进程,因此我们正在使用John Resig撰写的一种技术。。re using a technique written about by John Resig.
不是为每次mousemove
重置超时,而是mousemove
事件将设置一个变量,该变量可以由以受控速度运行的JavaScript间隔获取。。s running at a controlled pace.
var userActivity, activityCheck;
player.on('mousemove', function() {
userActivity = true;
});
activityCheck = setInterval(function() {
if (userActivity) {
userActivity = false;
if (player.userActive() === false) {
player.userActive(true);
}
clearTimeout(inactivityTimeout);
inactivityTimeout = setTimeout(function() {
if (!userActivity) {
this.userActive(false);
}
}, 2000);
}
}, 250);
这可能有点难以理解,而且与现在播放器中实际实现的功能相比,它被简化了一些,但本质上它允许我们在鼠标移动时减轻浏览器的一些处理负担。。s a bit simplified from what。s actually in the player now, but essentially it allows us to take some of the processing weight off of the browser while the mouse is moving.
得益于新的userActive状态和JavaScript超时延迟,控件不再需要鼠标移出播放器区域即可隐藏,现在可以在全屏模式下以与在页面中播放器相同的方式隐藏。这也意味着我们现在可以像隐藏控件一样隐藏鼠标光标,这样在全屏观看时它就不会停留在播放器上方。。t sit over the player while watching in fullscreen.
.vjs-fullscreen.vjs-user-inactive {
cursor: none;
}
触屏设备上的预期行为与桌面浏览器略有不同。没有mousemove
事件来帮助判断用户是活跃还是不活跃,因此通常会在控件淡出前添加更长的延迟。此外,虽然在桌面浏览器中点击视频本身通常会在播放和暂停之间切换,但移动设备上轻触视频会切换控件的可见性。
幸运的是,我们围绕userActive建立的框架使得最后一部分的设置变得足够简单。。ve set up around userActive has made this last part easy enough to set up.
video.on('tap', function() {
if (player.userActive() === true) {
player.userActive(false);
} else {
player.userActive(true);
}
});
在true和false之间手动切换userActive将应用适当的类名并触发显示和隐藏控件所需的事件,正如您在移动设备上所期望的那样。。d expect on a mobile device.
tap
事件实际上是一个自定义事件,类似于你在jQuery mobile、Hammer.js以及其他移动触控库中会发现的轻触事件。当touchstart
事件被触发,并且相关的touchend
事件在250毫秒内触发时,就会发生轻触事件。如果touchend
事件的触发时间更长,或者在这两个事件之间发生了touchmove
事件,则不被视为tap
。。ll find in jQuery mobile, Hammer.js, and other mobile touch libraries. A tap event occurs whenever a touchstart
event is fired with the associated touchend
event firing within 250 milliseconds. If the touchend
event takes longer to fire, or if a touchmove
event happens between the two, it is not considered a tap
.
我希望这能让你对Video.js中控件的这一部分如何运作,以及如果你正在为Video.js构建自己的插件时如何模仿相同的交互有所了解。我们始终感谢反馈。。re building your own plugins for Video.js. Feedback is always appreciated.
此致,
-heff 