微信小程序自带的 video 组件已经能够覆盖大部分视频播放场景,但真正要在业务里做好全屏播放和弹幕功能,还需要对组件的属性、事件以及视频上下文 API 有比较清晰的理解。很多人第一次接触时容易忽略组件在原生全屏与非原生全屏上的差异,或者不清楚弹幕数据到底该怎么组织才会被稳定渲染。下面先展示一张小程序视频组件的基础结构图,帮助你快速建立对 video 标签的认识。

准备工作:认识微信小程序video组件
video 组件是小程序内置的原生组件之一,它的层级最高,普通 view 无法覆盖在它上面。在页面中插入一个视频播放器,最基本的形式只需要一个 video 标签并指定 src 属性。不过为了获得更好的控制能力,通常还会设置 id、controls、show-center-play-btn、object-fit 等属性。其中 id 属性是后续通过 wx.createVideoContext 获取视频上下文的唯一标识,controls 控制是否显示默认播放控件,show-center-play-btn 决定是否显示中央播放按钮。
这里给出一个最简单的 video 组件示例,注意 id 需要和后面创建上下文时保持一致:
<video id="myVideo" src="https://ipipp.com/video.mp4" controls show-center-play-btn object-fit="contain" ></video>
video 组件还提供了 binderror、bindplay、bindpause、bindended 等事件,可以监听播放状态的变化。开发全屏功能时,我们会重点用到 fullscreenchange 事件,这个事件在视频进入或退出全屏时触发,回调参数中带有 fullScreen 和 direction 两个字段。弹幕功能则主要依赖 enable-danmu、danmu-btn、danmu-list 这三个属性,以及通过视频上下文调用 sendDanmu 方法。
需要特别注意的是,小程序基础库版本对 video 组件的能力有影响。例如 direction 属性在较旧的基础库中可能不支持,建议在开发前检查项目的最低基础库版本,或者在代码中做兼容性判断。
视频全屏播放的实现与细节处理
实现全屏播放有两种常见方式:一种是依赖 video 组件自带的控制条上的全屏按钮,用户手动点击后进入全屏;另一种是在业务逻辑中通过代码触发全屏。不管哪种方式,开发者都需要处理全屏方向、事件同步以及退出全屏后的状态恢复。video 组件的 direction 属性用于指定全屏方向,可选值包括 0(正常竖向)、90(屏幕逆时针旋转90度)、-90(屏幕顺时针旋转90度),默认值由系统自动判断。如果想强制横屏全屏播放,可以设置 direction="90" 或 direction="-90"。
监听 fullscreenchange 事件可以知道用户是否进入了全屏。事件对象 e.detail 中包含 fullScreen 布尔值和 direction 数值。当 fullScreen 为 true 时表示进入全屏,false 表示退出全屏。下面这段代码展示了如何监听全屏事件并在页面 data 中记录当前状态:
Page({
data: {
fullScreen: false
},
onVideoFullScreenChange(e) {
const { fullScreen, direction } = e.detail;
this.setData({
fullScreen,
fullDirection: direction
});
console.log('全屏状态变化:', fullScreen, '方向:', direction);
}
});
<video id="myVideo" src="https://ipipp.com/video.mp4" direction="90" bindfullscreenchange="onVideoFullScreenChange" ></video>
代码触发的全屏需要通过视频上下文对象来操作。先使用 wx.createVideoContext 获取上下文,然后调用 requestFullScreen 方法并传入方向参数。例如在点击某个按钮后强制横屏全屏播放:
onFullScreenTap() {
const videoCtx = wx.createVideoContext('myVideo');
videoCtx.requestFullScreen({ direction: 90 });
}
实际开发中还有一个容易踩坑的点:当用户通过默认控件进入全屏后,页面上的其他元素会被原生视频组件遮挡,而且全屏状态下无法通过 wx.navigateTo 跳转页面。因此如果业务需要在全屏时显示自定义弹幕层或交互按钮,建议使用同层渲染的 video 组件(即在 video 标签上加上 enable-page-gesture 属性),并配合 CSS 调整全屏页面的布局。
不同机型上的全屏行为也有细微差别,尤其是 Android 和 iOS 对 direction 值的处理可能不同。建议在真机上多次测试,必要时通过 wx.getSystemInfo 获取设备信息做针对性处理。
弹幕功能的开启与自定义发送
弹幕功能是 video 组件自带的能力,只需要正确配置属性即可开启。enable-danmu 属性控制是否开启弹幕,设置为 true 后视频才会显示弹幕轨道。danmu-btn 属性控制是否显示弹幕开关按钮,用户点击该按钮可以打开或关闭弹幕显示。danmu-list 是一个数组,用于初始化弹幕数据,每个弹幕对象包含 text(弹幕文本)、color(弹幕颜色)、time(弹幕出现时间,单位秒)。例如:
<video
id="myVideo"
src="https://ipipp.com/video.mp4"
enable-danmu
danmu-btn
danmu-list="{{danmuList}}"
></video>
Page({
data: {
danmuList: [
{ text: '这个视频真不错', color: '#ff0000', time: 2 },
{ text: '前方高能预警', color: '#00ff00', time: 5 }
]
}
});
用户主动发送弹幕需要调用视频上下文的 sendDanmu 方法。使用前同样需要先通过 wx.createVideoContext 获取上下文,然后传入 text 和 color 参数。发送后弹幕会立即显示在视频画面上,并且会自动记录到 danmu-list 中。下面是一个完整的发送弹幕交互示例:
onInputDanmu(e) {
this.setData({
danmuText: e.detail.value
});
},
onSendDanmu() {
const videoCtx = wx.createVideoContext('myVideo');
videoCtx.sendDanmu({
text: this.data.danmuText || '默认弹幕',
color: '#ffffff'
});
this.setData({
danmuText: ''
});
}
<input value="{{danmuText}}" bindinput="onInputDanmu" placeholder="输入弹幕内容" />
<button bindtap="onSendDanmu">发送弹幕</button>
弹幕的样式受到视频组件内部渲染机制的限制,开发者无法通过 CSS 直接修改单个弹幕的字体大小、边框等样式。但 color 属性支持任意合法颜色值,text 也支持部分文本样式。如果希望对弹幕做更高级的定制,例如自定义轨道、弹幕密度控制等,官方 video 组件可能无法满足,可以考虑使用 canvas 或第三方的弹幕组件叠加在视频上。不过那样会涉及同层渲染和性能问题,需要谨慎评估。
另外要注意 sendDanmu 方法在基础库 2.1.0 之前的版本中可能不存在,调用前最好使用 wx.canIUse 检查能力支持情况。弹幕列表数据量较大时也会影响视频渲染性能,建议在弹幕达到一定数量后清理过期的弹幕数据。
实战:结合全屏与弹幕的完整示例
下面把前面讲到的全屏控制和弹幕发送整合到一个页面中,形成一个可以直接运行的完整示例。页面包含一个 video 组件、一个输入框和一个发送按钮,同时监听全屏事件来更新页面状态。这个例子在开发者工具和真机上都能正常跑通。
<view class="container">
<video
id="myVideo"
src="https://ipipp.com/sample.mp4"
controls
direction="90"
enable-danmu
danmu-btn
danmu-list="{{danmuList}}"
bindfullscreenchange="onVideoFullScreenChange"
></video>
<view class="danmu-input-area">
<input value="{{danmuText}}" bindinput="onInputDanmu" placeholder="发条弹幕吧" />
<button bindtap="onSendDanmu">发送</button>
</view>
<view class="status">当前全屏状态:{{fullScreen ? '是' : '否'}}</view>
</view>
Page({
data: {
danmuList: [
{ text: '欢迎来到直播间', color: '#ffcc00', time: 1 },
{ text: '这个角度拍得真好', color: '#00ccff', time: 4 }
],
danmuText: '',
fullScreen: false
},
onInputDanmu(e) {
this.setData({
danmuText: e.detail.value
});
},
onSendDanmu() {
if (!this.data.danmuText) {
wx.showToast({ title: '请输入弹幕内容', icon: 'none' });
return;
}
const videoCtx = wx.createVideoContext('myVideo');
videoCtx.sendDanmu({
text: this.data.danmuText,
color: '#ffffff'
});
this.setData({
danmuText: ''
});
},
onVideoFullScreenChange(e) {
this.setData({
fullScreen: e.detail.fullScreen
});
}
});
代码中 direction="90" 让视频在进入全屏时强制横屏,但用户依然可以通过系统手势旋转屏幕。由于我们监听了 fullscreenchange 事件,所以页面上的状态提示能够实时更新。弹幕列表初始化了两条数据,用户输入的弹幕会通过 sendDanmu 方法出现在视频画面上。整个交互流程简单直观,适合作为二次开发的基础。
在实际项目中,你可能会遇到视频源地址无效、弹幕发送时机受播放状态限制等问题。建议在视频开始播放后再允许发送弹幕,可以通过监听 play 事件来控制发送按钮的可用性。同时,如果视频组件被销毁,记得调用 wx.createVideoContext 返回的上下文对象的 destroy 方法释放资源。掌握这些细节后,小程序视频组件的全屏与弹幕功能就能稳定地落地到业务中了。