最近想在自己的小程序当中实现以下多人实时弹幕的功能。查了各种资料后终于搞定,这里记录以下全过程
那么就先上小程序的菊花码为敬,可以先简单体验一下,废话不多说直接上主要部分的实现代码
1:基础内容准备
wxml
这一部分的内容非常简单,就是弹幕部分的wxml,不做过多的赘述了
<!-- 弹幕部分wxml-->
<view class="danmu">
<view wx:for="{{danmu}}" wx:key="*this" class="danmu-item" style="top:{{item.top}}rpx" animation="{{item.ani}}">
<image src="{{item.avatarUrl}}" mode="widthFix"></image>
<text>{{item.nickName}}</text>
<text> 选中了 {{item.text}}</text>
</view>
</view>
<!-- 由于想在弹幕中展示发送弹幕的用户的头像和微信名称,所以需要获取这两样东西-->
<button class="start" open-type="getUserInfo" bindgetuserinfo="btnClick">{{started ? '结束' : '换一个'}}</button>
wxss
这里就是最基础的css,没什么特别需要强调的东西。如果您只是想看实现的核心代码,请直接跳过。
.danmu{
position: absolute;
width: 750rpx;
top: 0;
z-index: 10;
}
.danmu-item{
display: flex;
position: absolute;
height: 34rpx;
padding: 3rpx 30rpx 3rpx 0;
line-height: 34rpx;
background-color: rgba(0,0,0,.7);
align-items: center;
border-radius: 15rpx;
transform: translate(790rpx,0);
}
.danmu-item image{
display: block;
position: relative;
width: 40rpx;
height: 40rpx;
margin-left: -20rpx;
margin-right: 10rpx;
border-radius: 20rpx;
overflow: hidden;
border: solid 1rpx #333;
}
.danmu-item text{
font-size: 25rpx;
color: #fff;
}
动画
其实弹幕的动画通过css也是一定可以实现,由于本人对于css动画确实已经用的比较多了,所以想尝试一下微信小程序的动画API。
wx.createAnimation({ duration: 7000 }).translateX(-500).step().export()
2:创建数据库 数据库权限设置
这里直接从云开发后台直接创建即可。
当然也有通过代码的创建方式,但此处并没有什么必要。
之后这里有很重要的一点,需要把数据库的权限设置为所有用户可读,仅创建者可写。
我在这个地方确实卡了一段时间,之前一直只能是看到自己发的弹幕。因为创建的时候是默认为仅创建者可读写,所以一直无法监听到
3:向数据库推送数据
这里的业务是当用户点击按钮,当用户选中某一个结果后向直接向数据库添加一条数据,也就是发送一条弹幕
// 用户的点击事件
btnClick() {
const _this = this
const menu = this.data.menu.split(' ')
const started = !this.data.started
this.setData({
started
})
if (started) {
const max = menu.length
timer = setInterval(() => {
const randomIndex = parseInt(max * Math.random())
const result = menu[randomIndex]
this.setData({
result
})
}, 100)
} else {
clearInterval(timer)
wx.getUserInfo({
lang: 'zh_CN',
success(res) {
const {
userInfo
} = res
_this.sendDanMu(userInfo)
},
fail(err) {
console.log(err)
_this.sendDanMu()
}
})
}
},
// 推送弹幕到数据库
sendDanMu({ avatarUrl = '', nickName = '不愿意透露姓名的神秘人' }) {
const text = this.data.result
db.collection('danmu').add({
data: {
avatarUrl,
nickName,
text
}
})
},
4:实时监听数据库
这里是实现实时弹幕的核心代码,通过集合进行监听,来完成弹幕的本地化
相关文档:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/realtime.html
// 监听danmu集合,同时在页面的onLoad当中进行调用
listenDanMu() {
const _this = this
db.collection('danmu')
.watch({
onChange: function (snapshot) {
// 在第一次调用watch的时候 snapshot.type 的值会为 init
// 这里强调在不为初始化、并且对集合执行的操作为add的时候,才会进行弹幕的生成
if (snapshot.type !== 'init' && snapshot.docChanges[0].dataType === 'add') {
const { avatarUrl, nickName, text } = snapshot.docChanges[0].doc
const item = {
avatarUrl,
nickName,
text,
top: Math.floor(Math.random()*(1 - 100) + 100) + 50
}
const danmu = _this.data.danmu
danmu.push(item)
_this.setData({
danmu
})
setTimeout(() => {
item.ani = wx.createAnimation({ duration: 7000 }).translateX(-500).step().export()
_this.setData({
danmu
})
}, 100)
}
},
onError: function (err) {
console.error('the watch closed because of error', err)
}
})
},
这里我有一点想说的,在尝试添加动画相关的那段代码的时候,发现必须要动画对隔一点时间在放到item中。
琢磨了一下,其实应该就是跟transition动画的原理差不多,需要有真正意义上的时间差。
当然如果这里有用的不对的地方请大佬指正。
5:定时清空数据库
新建云函数 (清空数据库)
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
console.log('清空danmu集合')
let res = await db.collection('danmu').where({
//每一条数据第一都会有_id,所以判断条件是_id不为空
_id: db.command.neq('')
}).remove()
console.log(res)
}
配置定时触发器
我制定的是凌晨3点半清空数据库danmu集合,相关的配置文档链接
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/triggers.html
"triggers": [
{
"name": "clearDanMu",
"type": "timer",
"config": "0 30 3 * * * *"
}
]
最后记得一定要将云函数和定时器发布上去
这是定时器调用成功的日志
最后在文末再放上菊花码,这篇文章如果对你有用的话,扫一下进去溜达一圈,让我也稍微挣点广告费啥的。。。
转载可以,要注明出处哦~