Videojs 全屏时显示弹幕和发送框
- Video.js 版本:7.10.2
- 弹幕库:https://github.com/weizhenye/Danmaku,2.0.2 版本
因为实现方式比较不规范,会深入 Video.js 内部 dom 进行操作,不确定是否适用其它版本。
全屏弹幕
我使用 vjs 的姿势是这样的:
1 | <div id="danmaku-container" ref={danmakuContainerRef} divdata-vjs-player> |
运行时发现它会展开成如下 dom 结构:
可以看到,video
还有其它 vjs 组件比如 vjs-control-bar
(控制条)都放在了 vjs_video_3
这个 div 下边。vjs 会操作这个 vjs_video_3
,给它增删几个 class, 实现 video 全屏/非全屏的切换。
我第一次尝试时,是直接将 danmaku-container
作为弹幕的容器传递给弹幕库的,即弹幕 div 是 danmaku-container
的最后一个子元素。但是全屏时就看不见弹幕了,我尝试调整弹幕的 z-index
,不起作用。这个问题到现在还没搞懂。
但是我发现,同样是 div 实现,控制条就可以总是显示在视频的上层。所以我尝试将弹幕放在跟 vjs-control-bar
同层:
1 | danmakuRef.current = new Danmaku({ |
danmaku-container
的 firstElementChild
也就是 vjs_video_3
了。
Okay,全屏时也可以看到弹幕了。但是 vjs_video_3
尺寸变化时没有通知到弹幕 div,这个需要自己处理:
1 | new ResizeObserver(entries => { |
videoElement
是 video
的对象,换成 vjs_video_3
应该也是一样的。resize()
是我用的弹幕库的接口方法,按构造时传入的容器尺寸自动计算新尺寸,省了自己传递参数。
好了!不需要调整 position 乱七八糟,到这里弹幕的显示就已经完美了。
发送框显示在视频之上
vjs 支持扩展 vjs-control-bar
。vjs-control-bar
里有一个 vjs-custom-control-spacer
组件,可以将自己的 UI 填充到里边。但问题是控制条总共就那么宽,如果过多自定义 UI 的话,势必显得很拥挤。
所以还是基于弹幕显示的原理,组合好发送 UI 之后,把最外层的 div 添加到 vjs_video_3
,这种实现方式的自由度最高:可以自定义任何尺寸和位置:
1 | div.style.position = "absolute"; |
我折腾的过程中发现,vjs 同样是通过操作 vjs_video_3
的 css 类实现控制条的显示/隐藏的:
1 | // @see https://github.com/videojs/video.js/blob/main/src/js/player.js |
vjs 没有直接引用控制条的 dom 对象,而是通过动态生成后代选择器控制控制条的显示/隐藏:
1 | .vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { |
这个信息有大用,因为我可以将我发送框 div 的类名指定为 vjs-control-bar
,这样,输入框的显示/隐藏就可以跟控制条保持一致了!不需要再自己写控制逻辑了!
web 真好玩~