此文主要通过小程序+网页模拟多客户端通过轮询、WebSockets、订阅推送等方式简易实现实时弹幕。
- 打开Visual Studio,创建新项目,选择包含API的应用程序模板。
- 填写项目名称及选择对应的保存位置,框架版本可根据开发习惯来选择。
- 服务端主要用于搭建API接口,选择MVC,其他选项默认即可。
- 选中项目Models文件夹,创建一个实体类用于定义推送到客户端的各个字段属性值。
- 实体类中定义字段如下:弹幕内容、发送时间、发送人、来源、是否推送等,字段可根据实际业务场景来增减。
public class Barrage {
/// <summary>
/// 弹幕内容
/// </summary>
public string BarrageContent { get; set; }
/// <summary>
/// 发送时间
/// </summary>
public DateTime SendTime { get; set; }
/// <summary>
/// 发送人
/// </summary>
public string CreateBy { get; set; }
/// <summary>
/// 来源 小程序 / web端
/// </summary>
public string From { get; set; }
/// <summary>
/// 是否推送
/// </summary>
public int IsPush { get; set; }
}
- 打开Controller文件夹中的Home控制器,定义两个方法以及一个List,分别用于接收存储以及弹幕推送等功能;这里需要注意的是每次只需要获取未推送的弹幕消息即可,获取弹幕的接口被调用后,即将推送过去的数据修改为已推送。
/// <summary>
/// 需要推送的弹幕数据
/// </summary>
List<Barrage> list = new List<Barrage>();
/// <summary>
/// 提交弹幕
/// </summary>
/// <param name="BarrageContent"></param>
/// <param name="CreateBy"></param>
/// <param name="From"></param>
/// <returns></returns>
public ActionResult ReceivingBarrage(string BarrageContent,string CreateBy,string From) {
Barrage info = new Barrage();
info.BarrageContent = BarrageContent;
info.CreateBy = CreateBy;
info.From = From;
info.SendTime = DateTime.Now;
info.IsPush = 0;
list.Add(info);
return Json("提交弹幕");
}
/// <summary>
/// 获取弹幕内容
/// </summary>
/// <returns></returns>
public ActionResult AcquireBarrage() {
//根据时间排序获取未推送的数据
var BarrageList = list.Where(x=>x.IsPush == 0).OrderByDescending(z=>z.SendTime);
//数据推送后 将类型改为已推送
return Json(BarrageList);
}
- 访问微信公众平台,点击账号注册。
- 选择小程序,并在表单填写所需的各项信息进行注册。
- 在开发管理选择开发设置,将AppID及AppSecret复制出来进行存储。
- 下载安装微信web开发者工具并创建一个新的项目,填入上图所复制的AppId。
- 在小程序创建一个组件用于展示弹幕效果。
- 组件所需属性值:距离屏幕顶部距离、行距单位、数据源、层级、弹幕行数等。
/**
* 组件的属性列表
*/
properties: {
//距离屏幕顶部距离
top: {
type: String,
value: "10vh"
},
//每行间距单位
rowSpacing: {
type: String,
value: "40rpx",
},
//数据源
list: {
type: Array,
value: []
},
//层级
zIndex: {
type: Number,
value: 999
},
//一个等于屏幕宽度的弹幕 滚动所需要的时间 单位毫秒
speed: {
type: Number,
value: 10000
},
//动画速度波动范围-500~500ms之间选取随机值,用于控制每条弹幕的速度
shakeSpeed: {
type: Number,
value: 500
},
//动画延时执行时间波动范围上限值 0~500ms之间选取随机值, 用于控制弹幕出厂顺序
shakeDelay: {
type: Number,
value: 500
},
//弹幕行数
rows: {
type: Number,
value: 2
},
//每项弹幕右外边距
marRight: {
type: String,
value: "40rpx"
},
//是否循环
loop: {
type: Boolean,
value: false
}
},
- 在组件wxml文件中将弹幕数据进行渲染。
<view animation="{{item.animation}}" wx:for="{{barrageInfo.list}}"
style="z-index:{{zIndex}};top:{{item.top?item.top:top}}" class="barr" id="barr_{{index}}">
<view class="item" wx:for-item="_item" style="margin-right:{{marRight}}" wx:for="{{item.list}}">
<view class="box">
<image src="{{_item.avatar}}"></image>
<text>{{_item.words}}</text>
</view>
</view>
</view>
- 创建一个新的page,用于视频展示及弹幕推送等效果,同时在json文件中引用上面所创建的组件。
{
"usingComponents": {
"barrage": "/components/barrage"
}
}
- 准备一个MP4格式的素材模拟数据源或者直播效果,同时在wxml中将组件及video将数据进行展示。
- 通过HBuiderX开发工具创建一个默认的网站项目。
- 在index.html文件中简单实现弹幕展示及video效果。
<script>
var inputText = document.getElementById("text");
var danmuArea = document.getElementById("danmuArea");
var colorInput = document.getElementById("textcolor");
function sendDanmu() {
var text = inputText.value;
var msg = document.createElement("p");
msg.innerText = text
msg.style.color = colorInput.value;
var top = Math.random() * 280;
msg.style.top = top + "px";
danmuArea.appendChild(msg)
msg.setAttribute("class", "msg")
inputText.value = "";
}
</script>
- 前期工作准备好后,再次回到小程序客户端;在页面增加一个文本框以及按钮用于获取所输入的弹幕信息及实现发送等功能。
- 文本框绑定bindinput事件,获取用户输入的弹幕内容。
bindMsg(e) {
this.setData({
msg: e.detail.value
});
},
- 发送按钮绑定点击事件,给data中的list追加数据的同时调用API接口,提交数据。
let that = this;
let info = {
"words": that.data.msg,
"avatar": "../../images/head.jpg"
};
that.setData({
barrageList: that.data.barrageList.concat(info),
msg:'',
});
wx.request({
url: that.data.requestUrl + '/Home/ReceivingBarrage',
method: 'post',
data: {
BarrageContent: that.data.msg,
CreateBy: '摔跤猫子',
From: '小程序'
},
header: {
'content-type': 'application/json'
},
success: function (res) {
}
})
- 在onLoad事件中增加一个定时轮询请求,每隔1s请求一次,如果有数据即向弹幕list中进行推送。
setInterval(() => {
wx.request({
url: that.data.requestUrl + '/Home/AcquireBarrage',
method: 'post',
header: {
'content-type': 'application/json'
},
success: function (res) {
that.setData({
barrageList:that.data.barrageList.concat(res.data)
});
}
})
}, 1000);
- 在web客户端中依法炮制,获取弹幕,发送弹幕即可。
后续更新实现代码;大体实现原理即利用WebSocket即时通信节省大量无效请求,减轻服务器压力和网络带宽的占用;服务器可以主动向客户端推送消息,客户端也可以主动向服务端发送消息,双向平等对话。
后续更新实现代码;