我的想法:我要用 danmu-list 做一个动态的视频弹幕
思路:我通过 bindtimeupdate 这个事件,一直在监听当前视频的进度,来获取弹幕的发送时间,从而把弹幕显示在视频上,我中间给了2s的延迟,在我监听到当前视频进度秒的时候,会向上取整,并且加2s作为弹幕在视频上的显示时间。让用户输入文字后,点击发送,我会构建一个数组,对 danmu-list 进行setdata,重新渲染页面。
问题:这样的写法在模拟器上没有任何问题,但是在手机端会出先失效、混乱的问题
手机设备:Android 华为 V9
手机端出现的问题:
1:当这个视频之前没有任何弹幕的时候,在手机端进行操作,可以把输入的弹幕显示在视频上,但是每次显示最新一条的时候,会把上一条的弹幕内容带上。
2:当这个视频存在弹幕的时候,也就是本身具有弹幕列表了,然后再进行操作,这个时候手机端输入文字,不能显示到视频列表中,只要把视频暂停后,然后拖回之前的时间,再进行一次播放,方可显示出来。
猜想:
我自己调试了很长时间,做了好几种假设,比如是否是我延迟时间给的太短,是否是数组的顺序不对。但是我发现都不是这些问题,最后,我再想,是否是setdata后 setdata进行页面渲染的时候,在手机端因为计算能力没电脑那么强,所以渲染的时间比较长,会让我错过弹幕该显示的时间点。如果是这个样子,我想请求官方告诉我,小程序setdata后 在自己渲染页面的时候会使用多久的时间才能完全渲染完,这样我就知道我改如何去控制用户在一定的时间范围内,才能发送弹幕。
代码:
wxml
<view class="vid">
<video class='videos' id="myVideo" src='{{ImageServiceUrl+param.url}}' controls='controls' autoplay="true" poster="{{ImageServiceUrl+param.pic}}" objectFit="fill" danmu-list="{{danmu_list}}" danmu-btn="true" enable-danmu="true" bindtimeupdate="VideoChange"></video>
</view>
<scroll-view scroll-y="true" class='list' style='height:{{windowHeight-260}}px;' scroll-into-view="{{Toview}}">
<view class='list1' id='ID-{{index}}' wx:for="{{danmu_list}}" wx:key="itme">
<text style='color:#9b9b9b;'>{{item.name}}-{{item.time}}:</text>
<text style='color:#000;'>{{item.text}}</text>
</view>
</scroll-view>
<view class='inps'>
<form bindreset="formReset">
<input class='skl' id='DanMuContentID' placeholder='说点什么吧。。' adjust-position="false" bindinput="CompleteContent" confirm-type="发送" ></input>
<button class='send' wx:if="{{!user_info}}" bindgetuserinfo='SendContentH' open-type="getUserInfo" form-type='reset'>发送</button>
<button class='send' wx:if="{{user_info}}" bindtap='SendContentQ' form-type='reset' >发送</button>
</form>
</view>
JS:
// pages/video/play_video.js
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
ImageServiceUrl: app.globalService.ImageServiceUrl,
MaxCount:1,
ContentTime: 0,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this;
console.log(options);
var pt_user = wx.getStorageSync('pt_user');
var user_info = wx.getStorageSync('user_info');
wx.setNavigationBarTitle({
title: pt_user.hospital_title,
});
var CurrentTime = Date.parse(new Date());
var CurrentContentTime = CurrentTime / 1000;
wx.getSystemInfo({
success(Winres) {
wx.request({
url: app.globalApiList.SelectDanMu,
data:{'id':options.id,'type':options.type},
success:function(res){
that.setData({
windowHeight: Winres.windowHeight,
param: options,
user_info: user_info,
Toview: 'ID-' + res.data.data.MaxCount,
MaxCount: res.data.data.MaxCount,
ContentTime: CurrentContentTime,
danmu_list: res.data.data.list,
})
}
})
}
})
var videoContext = wx.createVideoContext('myVideo');
//videoContext.requestFullScreen();
},
/**
* 发送弹幕-获取信息
*/
SendContentH:function(e){
app.SetUserInfo(e.detail.userInfo);
this.SendContentApi(e.detail.userInfo);
},
SendContentQ:function(){
this.SendContentApi(this.data.user_info);
},
/**
* 发送内容与后台交互
*/
SendContentApi:function(userinfo){
if (this.globalData.user_text){
var ContentTime = this.data.ContentTime;
var CurrentTime = Date.parse(new Date()) / 1000;
var DiffentTime = CurrentTime - ContentTime;
if (DiffentTime > 3){
var pt_user = wx.getStorageSync('pt_user');
var MaxTime = this.globalData.MaxTime;
var color_key = Math.floor(Math.random() * app.globalData.color.length);
var danmu_list = this.data.danmu_list;
var MaxCount = this.data.MaxCount + 1;
var danmu = {
text: this.globalData.user_text,
color: app.globalData.color[color_key].number,
time: MaxTime,
name: userinfo.nickName
};
danmu_list.push(danmu);
this.setData({
user_info: userinfo,
danmu_list: danmu_list,
Toview: 'ID-' + MaxCount,
MaxCount: MaxCount,
});
app.HideNoticeMessage(MaxTime.toString());
console.log(this.data.danmu_list);
wx.request({
url: app.globalApiList.SaveDanMu,
data:{
text: this.globalData.user_text,
name: userinfo.nickName,
type:this.data.param.type,
userid:pt_user.user_id,
id:this.data.param.id,
color: app.globalData.color[color_key].number,
time: MaxTime,
},
success:function(res){
}
})
}else{
app.HideNoticeMessage('请'+DiffentTime+'秒后再进行发言');
}
}else{
app.HideNoticeMessage('说点什么嘛~');
}
},
/**
* 文字输入完毕的时候
*/
CompleteContent:function(res){
this.globalData.user_text=res.detail.value;
},
globalData: {
user_text:null,
videoObject:null,
MaxTime:0,
},
/**
* 视频播放进度变化时出发
* 间隔 250ms
*/
VideoChange:function(res){
this.globalData.MaxTime = Math.ceil(res.detail.currentTime) + 3;
},
/**
* 重置表单
* 其实我搞不懂什么都不需要写
* 为什么不可以用JS直接调用某个方法呢?
* 很尴尬
* 感觉像是要去某一个地方,但是我必须要绕一个圈子才能到达
* 或许这是因为某些机制
* 但是希望微信可以尽快让开发者别再绕来绕去
* 其实我本意只是想清空input里面的值
* 但是走这么多的步骤。
*/
formReset:function(res){
}
})
我也是在添加 bindtimeupdata 事件后,弹幕出现错乱的问题,不监听这个事件是没有问题的,但存储弹幕的时候又需要这个时间戳,楼主怎么解决的
@你剑哥,我还真没注意这种情况,谢谢提醒,我自己测试下
我用过 sendDanmu 这个API来发送弹幕,但是这个API很不稳定,容易发不出来
@楼主,你可以尝试一下使用sendDanmu这个api来发送弹幕,而不是setData
麻烦给个相关的代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html),我们定位下问题
我今天发现new Date(),在真机打印出来的时间和在模拟器上打印出来的时间差几个小时,你有这种情况么?百思不得其解。