本文会从产品角度来讲诉如何打造一款支持表情的弹幕小程序
产品需求:演唱会应援、行走的广告牌以及地铁让座提醒等等(提供一种思路)
竞品分析:小程序里的弹幕类应用大部分只支持文字,而图片和音频这一块功能是缺失的
功能确定:支持滚动文字和滚动图片
实现效果
思路:
input 获取输入文字,richtext显示包含图片的弹幕,设置richtext中文字的方向并滚动起来,滑动改变文字大小,文字颜色等操作
实现代码:
1.使用input输入文字、支持emoji表情
先定义的一个"danmu"对象来保存input输入的弹幕文字以及弹幕样式、
danmu: {
fontColor: "#ffffff",
text: "默认弹幕~",
fontSize: "40px",
glow: "#ffff00",
speed: '10s',
},
复制代码
接着定义"nodes"对象显示数据 text:弹幕文字;fontSize:文字大小;fontColor:文字颜色;glow:文字发光;speed:滚动速度。
使用input组件输入文字:
<input type='text'
bindconfirm='changeDanmuText'
value='{{danmu.text}}'
placeholder='输入弹幕~'
placeholder-style='color:#fff'
cursor-spacing='28'>
</input>
复制代码
cursor-spacing设置input中光标与键盘的距离
2.richText显示包含图片的弹幕
定义nodes对象来更新弹幕
nodes: [{
name: 'div',
attrs: {
class: 'danmu-text'},
children: [
{
type: 'text',
text: '弹幕文本?~'},
{
name: 'img',
attrs: {
src: '网络图片',
width: '数值',
style: '样式'}
}
]
}],
复制代码
nodes的children是一个节点集合,type是类型,text类型只有text对象,默认是节点类型所以不需要type,节点类型中name是指节点名,attrs是指节点的属性。
具体方法属性可以看官方 richText 文档
danmu对象与rich-text组件绑定数据关系,
<rich-text nodes='{{nodes}}'
class='rich-text'
style='font-size:{{danmu.fontSize}};color:{{danmu.fontColor}};text-shadow: 0 0 20rpx {{danmu.glow}};'>
</rich-text>
复制代码
并更新弹幕数据在rich-text组件上
changeDanmuText: function () {
if (that.data.danmu.text != '') {
that.data.nodes[0].children = []
that.data.nodes[0].children.push({
type: 'text',
text: that.data.danmu.text
})
that.setData({
danmu: that.data.danmu,
nodes: that.data.nodes
})
}
},
复制代码
判断弹幕数据,如果是有有效数据则push到children中,并立即更新数据
经过以上两步,已经可以把input中的数据展示在rich-text中了。
滚动弹幕样式,利用animation 的transform: translate3d,设备会开启GPU加速
rich-text {
width: auto;
height: auto;
display: inline-block;
}
.danmuContent {
animation: danmuAnimation 10s;
animation-iteration-count: infinite;
animation-timing-function: linear;
display: inline-block;
text-shadow: 0 0 20rpx #f00;
transform: rotate(90deg);
transform-origin: 0% 100%;
writing-mode: vertical-lr;//很重要,把文字竖着排列
text-orientation: sideways-right;//改变文字方向
}
@keyframes danmuAnimation {
from {
transform: translate3d(0, 100%, 0);
}
to {
transform: translate3d(0, -100%, 0);
}
}
复制代码
<view style='display:flex;align-items:center;justify-content:center;'>
<view class='danmuContent' style='min-height:{{view.height}};animation-duration:{{danmu.speed}}'>
<rich-text nodes='{{nodes}}' class='rich-text' style='font-size:{{danmu.fontSize}};color:{{danmu.fontColor}};text-shadow: 0 0 20rpx {{danmu.glow}};'>
</rich-text>
</view>
</view>
复制代码
下面就要插入表情和更新文字样式
3.插入动态表情
定义动态表情url数组gifUrl = [url0,url1,url2,....]
复制代码
显示在view中
<view wx:for="{{gifUrl}}" wx:for-item="url" class='gif'>
<image src='https://user-gold-cdn.xitu.io/2018/1/13/160ef9d4a180eee1' data-gifid='https://user-gold-cdn.xitu.io/2018/1/13/160ef9d4a180eee1' bindtap='addImg' class='gif'>
</image>
</view>
复制代码
gifid传到nodes中的img src里,之后更新数据
addImg: function (e) {
that.data.nodes[0].children.push({
name: 'img',
attrs: {
src: e.currentTarget.dataset.gifid,
width: '40px',
style: 'transform:rotate(90deg)'
}
})
that.setData({
nodes: that.data.nodes,
danmu: that.data.danmu
})
},
复制代码
4.设置文字大小、颜色、发光以及滚动速度
这一步其实不难,主要就是交互上要简洁、方便。
使用slider滑动改变文字大小<slider bindchange='changeFontSize'
bindchanging='changeFontSize'
show-value='true' min='10' max='200'>
</slider>
复制代码
文字颜色和发光颜色,使用slider模拟了一个滑动取色(这个后续文章详细分析)
changeFontColor: function (e) {
let H = e.detail.value
let color = this.HSB2RGB([H, 1, 1])
this.data.danmu.fontColor = 'rgb(' + color.R + ',' + color.G + ',' + color.B + ')'
this.setData({
danmu: this.data.danmu
})
},
changeFontGlow: function (e) {
let H = e.detail.value
let color = this.HSB2RGB([H, 1, 1])
this.data.danmu.glow = 'rgb(' + color.R + ',' + color.G + ',' + color.B + ')'
this.setData({
danmu: this.data.danmu
})
},
复制代码
弹幕滚动速度同样使用slider,取值1-3,避免太快。
<slider bindchange='changeFontSpeed'
bindchanging='changeFontSpeed' show-value='true' min='1' max='3'>
</slider>
复制代码
为了保持滚动速度的均匀,要根据弹幕view的高度实时改变(animation-duration),达到匀速的目的。
changeFontSpeed: function (e) {
let speedValue = e.detail.value / 4 * 100
wx.createSelectorQuery().selectAll('.danmuContent').boundingClientRect(function (rects) {
rects.forEach(function (rect) {
that.data.danmu.speed = rect.height / speedValue + 's'
that.setData({
danmu: that.data.danmu
})
})
}).exec()
},
复制代码
到这里,基本功能已经实现,还有其他操作,比如保持屏幕常亮、屏幕上背景全黑并隐藏其它内容。
// 保持屏幕常亮
wx.setKeepScreenOn({
keepScreenOn: true
})
复制代码
设置导航栏颜色
wx.setNavigationBarColor({
frontColor: '#000000',
backgroundColor: '#000000',
})
复制代码
总结
滚动弹幕动画要考虑手机的性能,没有使用canvas,最直接就是使用css的transform动画,效率最高。 小程序的富文本编辑支持比较弱,尝试了许多方法,比如在文字中插入图片,想到了类似QQ表情"[微笑/]"的方法,使用正则进行分析,再显示在rich-text上,但是在这个项目上不合适。只好换一种思路,在文字开头或结尾插入图片。
以上代码没做相关优化,写的比较糙,把我的思路写出来给大家看看,共同成长! 一个射鸡狮的不归之路~