1、在直播页面的弹幕评论中,我们希望的样式是: 观众名字:评论
而且颜色有所区分,并在同一行显示
2、我们希望在发弹幕的时候可以回自动滚动到自己发的内容那里
一:弹幕样式修改
因为是小白,前端对于样式这一块实在是太难了,只能一边百度学习一边修改,踩坑无数,最终达到自己想要的效果,在此记录一下。
1.1:目标效果图:
1.2:踩坑记录
(我这个使用的是nvue页面,在使用大佬的页面模板下样式发生了改变,只能自己慢慢修改调整)
因为这个名字和弹幕内容需要颜色区分开,所以我本来打算的是使用两个text组件,颜色分别设置,最后给父元素使用flex-direction: row让他们在同一行即可,但是这样使用的话会导致弹幕文字直接溢出灰色背景不会换行;如果再给它的父元素添加flex-wrap: wrap;很不幸,这样不仅导致子元素全部换行,也就是名字和弹幕占据两行,而且文字的溢出也没有解决,实在是头大,最终还是找到大佬的解决方案(https://www.cnblogs.com/robot666/p/14987404.htmlhttps://www.cnblogs.com/robot666/p/14987404.html),使用一个rich-text替代两个text,在这里分别设置不同的样式和内容
1.3:代码
这是templete代码,里面我使用:style="{ width: computedWidth(item) + 'rpx' 来设置弹幕的灰色背景,使其有不同宽度的背景
<view id="scroll-view-content">
<view class="remind">{{ remind }}</view>
<view class="main">
<view class="plMaim" v-for="(item, index) in danmuData" :key="index" :id="'item-' + index"
:style="{ width: computedWidth(item) + 'rpx' }">
<!-- <text class="myName">{{ item.name }}:</text>
<text class="myPl">{{ item.content }}</text> -->
<rich-text :nodes="richNodes(item)"></rich-text>
</view>
</view>
</view>
下面是script代码,可以根据自己情况设置
richNodes(item) { //弹幕样式计算
return [{
children: [{
type: 'text',
attrs: {
style: 'color: #a1e5fc; font-size: 32rpx; line-height: 36rpx; padding: 8rpx; border: #ffff7f solid 1px;'
},
text: item.name + ':'
},
{
type: 'text',
attrs: {
style: 'color: #ffffff; font-size: 32rpx; line-height: 36rpx; padding: 8rpx; border: #ffff7f solid 1px; '
},
text: item.content
}]
}];
}
二、发送弹幕自动滚到内容处
2.1:方式一:滚动视图减去不需要的视图高度
这个我先使用百度到的方式,原理是:uni .createSelectorQuery().in(this)使用这个api,获取到可滚动视图的总高度,通过减去弹幕区域固定的高度,剩余的就是我们不需要的高度,我们只需要将这个剩余高度设置为可滚动区域的顶部,就相当于滚动到弹幕底部了,代码我放在下面。但是我在使用这个时出现了问题,具体报错如下图,我研究了好一会,但是不明白,只能采用第二个方式。
<scroll-view :style="{ height: scrollViewHeight + 'px' }" :scroll-y="true" :scroll-top="scrollTop"
:scroll-with-animation="true" :scroll-y-bar="false" show-scrollbar class="scrollView" ref="scrollViewRef">
<view id="scroll-view-content">
<view class="remind">{{ remind }}</view>
<view class="main">
<view class="plMaim" v-for="(item, index) in danmuData" :key="index"
:style="{ width: computedWidth(item) + 'rpx' }">
<!-- <text class="myName">{{ item.name }}:</text>
<text class="myPl">{{ item.content }}</text> -->
<rich-text :nodes="richNodes(item)"></rich-text>
</view>
</view>
</view>
</scroll-view>
<script>
export default {
data() {
return {
//滚动条位置
scrollTop: 0,
scrollViewHeight: 191, //滚动视图的高度
}
}
}
methods: {
//发送按钮
sendOut() {
if(this.content){
const list = {
name: this.nickname,
content: this.content,
};
this.danmuData.push(list);
this.content = ''
this.scrollToBottom();
}},
//根据内容自动滚动
scrollToBottom() {
this.$nextTick(() => {
uni
.createSelectorQuery()
.in(this)
.select("#scroll-view-content")
.boundingClientRect((res) => {
let top = res.height - this.scrollViewHeight;
if (top > 0) {
this.scrollTop = top;
}
})
.exec();
});
},
}
</script>
2.2:方式二:根据索引滚动到指定位置
可以在展示每条弹幕消息中加上索引:id="'item-' + index",根据索引滚动
<scroll-view :style="{ height: scrollViewHeight + 'px' }" :scroll-y="true"
:scroll-with-animation="true" :scroll-y-bar="false" show-scrollbar class="scrollView" :scroll-into-view="scrollToView">
<view id="scroll-view-content">
<view class="remind">{{ remind }}</view>
<view class="main">
<view class="plMaim" v-for="(item, index) in danmuData" :key="index" :id="'item-' + index"
:style="{ width: computedWidth(item) + 'rpx' }">
<!-- <text class="myName">{{ item.name }}:</text>
<text class="myPl">{{ item.content }}</text> -->
<rich-text :nodes="richNodes(item)"></rich-text>
</view>
</view>
</view>
</scroll-view>
在点击发送按钮后执行下面的方法,把当前用户的名字发送过来进行匹配,获取最后一个即可
//根据索引滚动
scrollToBottom(name) {
this.$nextTick(() => {
const index = this.danmuData
.map((item, i) => item.name === name ? i : -1)
.filter(i => i !== -1)
.pop(); // 获取最后一个匹配项的索引
if (index !== undefined) {
this.scrollToView = 'item-' + index;
}
});
},