|
@@ -29,13 +29,24 @@
|
|
|
:picture-in-picture-mode="[]"
|
|
|
:show-background-playback-button="false"
|
|
|
:src="videoUrl"
|
|
|
- :danmu-list="danmuList"
|
|
|
+ >
|
|
|
+ <!-- :danmu-list="danmuList"
|
|
|
enable-danmu
|
|
|
- danmu-btn>
|
|
|
+ danmu-btn -->
|
|
|
+ <template v-show="showDanmu==1">
|
|
|
+ <text v-for="(item, index) in activeDanmus" :key="item.id" class="danmu-item danmuMove"
|
|
|
+ :style="{
|
|
|
+ top: item.top + 'px',
|
|
|
+ ...item.style,
|
|
|
+ 'animation-duration': '8s'
|
|
|
+ }" @animationend="animationend(item,index)">
|
|
|
+ {{ item.text }}
|
|
|
+ </text>
|
|
|
+ </template>
|
|
|
<cover-view class="video-danmu-btnbox" :style="{display: isfull&&crtShow&&isLogin&&isAddKf==1 ? 'block':'none'}">
|
|
|
- <cover-image class="video-danmu-image"
|
|
|
- src="https://cos.his.cdwjyyh.com/fs/20250418/beaf9df1a6204b8babc3e28d9b563c62.png"
|
|
|
- @click="openDanmu(1)"></cover-image>
|
|
|
+ <cover-image class="video-danmu-image"
|
|
|
+ src="https://cos.his.cdwjyyh.com/fs/20250418/beaf9df1a6204b8babc3e28d9b563c62.png"
|
|
|
+ @click="openDanmu(1)"></cover-image>
|
|
|
</cover-view>
|
|
|
</video>
|
|
|
</view>
|
|
@@ -103,7 +114,7 @@
|
|
|
<!-- 线路 -->
|
|
|
<view class="video-line" @click="openPop" v-if="isLogin&&isAddKf==1">
|
|
|
<image :src="baseUrl+'/images/changePlayer-icon.png'"></image>
|
|
|
- <text>线路{{lineIndex + 1 | numberToChinese}}</text>
|
|
|
+ <text>线路{{numberToChinese(lineIndex + 1)}}</text>
|
|
|
</view>
|
|
|
<!-- 线路弹窗 -->
|
|
|
<uni-popup ref="popup" type="bottom" class="full-width-popup">
|
|
@@ -116,7 +127,7 @@
|
|
|
<view class="popupbox-content">
|
|
|
<view :class="lineIndex == index ? 'line-item line-active': 'line-item'"
|
|
|
v-for="(it,index) in lineList" :key="index" @click="handleLine(index)">
|
|
|
- 线路{{index + 1 | numberToChinese}}</view>
|
|
|
+ 线路{{numberToChinese(lineIndex + 1)}}</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</uni-popup>
|
|
@@ -129,6 +140,7 @@
|
|
|
<uni-popup ref="danmuPopup" type="bottom" style="z-index: 999;" @change="changeShowPopup">
|
|
|
<view class="danmuPopup" :style="{marginLeft:isfull ? statusBarHeight+'px': 0,marginBottom: danmuboxHeight+'px'}">
|
|
|
<view class="danmuPopup-head border-line">
|
|
|
+ <image class="danmu-icon" :src="showDanmu==0?'/static/images/danmu-off.png':'/static/images/danmu-on.png'" mode="heightFix" @click="switchDanmu()"></image>
|
|
|
<u-input
|
|
|
class="danmuPopup-input"
|
|
|
placeholder="发个弹幕吧~"
|
|
@@ -139,7 +151,7 @@
|
|
|
:autoBlur="true"
|
|
|
maxlength="140"
|
|
|
clearable
|
|
|
- v-model="danmuIput"></u-input>
|
|
|
+ v-model.trim="danmuIput"></u-input>
|
|
|
<button class="danmuPopup-send" :disabled="danmubtnLoading" @click="sendDanmu">发送</button>
|
|
|
</view>
|
|
|
</view>
|
|
@@ -334,19 +346,21 @@
|
|
|
danmuboxHeight: 0,
|
|
|
user: {},
|
|
|
crtShow: true,
|
|
|
- isCheckRealUrl: false
|
|
|
+ isCheckRealUrl: false,
|
|
|
+ activeDanmus:[],
|
|
|
+ flagTime: 0,
|
|
|
+ danmuItemStyle:{
|
|
|
+ color: '#ffffff',
|
|
|
+ fontSize: '16px',
|
|
|
+ border: 'solid 1px #ffffff',
|
|
|
+ borderRadius: '5px',
|
|
|
+ padding: '2px 2px',
|
|
|
+ backgroundColor: 'rgba(255, 255, 255, 0.1)'
|
|
|
+ },
|
|
|
+ showDanmu: 1,
|
|
|
+ ctx: null
|
|
|
}
|
|
|
},
|
|
|
- filters: {
|
|
|
- numberToChinese(number) {
|
|
|
- if (number) {
|
|
|
- const chineseNumber = ['一', '二', '三', '四', '五', '六', '七', '八', '九'];
|
|
|
- return chineseNumber[number - 1];
|
|
|
- } else {
|
|
|
- return ''
|
|
|
- }
|
|
|
- },
|
|
|
- },
|
|
|
computed: {
|
|
|
isAnswer() {
|
|
|
return (item, name) => {
|
|
@@ -372,19 +386,9 @@
|
|
|
// this.loginByMp()
|
|
|
// }
|
|
|
var that=this;
|
|
|
- // this.videoId=769;
|
|
|
- // this.qwUserId=2110;
|
|
|
- // this.corpId='ww5a88c4f879f204c5';
|
|
|
- // this.linkType=0;
|
|
|
- // this.urlOption.videoId=769;
|
|
|
- // this.urlOption.courseId=79;
|
|
|
- // this.urlOption.companyId=170;
|
|
|
- // this.urlOption.companyUserId=3972;
|
|
|
- // this.urlOption.qwUserId=1;
|
|
|
- // this.urlOption.corpId='ww5a88c4f879f204c5';
|
|
|
- // this.urlOption.qwExternalId=6213064;
|
|
|
- // this.urlOption.qwUserId=2110;
|
|
|
- // this.urlOption.linkType=0;
|
|
|
+ if (this.videoId) {
|
|
|
+ this.getH5CourseByVideo()
|
|
|
+ }
|
|
|
this.sortLink = this.urlOption.link || ''
|
|
|
this.getMenuButton()
|
|
|
// #ifndef H5
|
|
@@ -395,6 +399,7 @@
|
|
|
clearInterval(this.pingpangTimes)
|
|
|
this.socket = null
|
|
|
}
|
|
|
+ this.initTracks()
|
|
|
},
|
|
|
onShow() {
|
|
|
this.tipsOpen = false
|
|
@@ -406,9 +411,6 @@
|
|
|
} else {
|
|
|
this.user = {}
|
|
|
}
|
|
|
- if (this.videoId) {
|
|
|
- this.getH5CourseByVideo()
|
|
|
- }
|
|
|
if(this.sortLink){
|
|
|
this.getLink()
|
|
|
} else {
|
|
@@ -468,6 +470,14 @@
|
|
|
this.clearIntegral()
|
|
|
},
|
|
|
methods: {
|
|
|
+ numberToChinese(number) {
|
|
|
+ if (number) {
|
|
|
+ const chineseNumber = ['一', '二', '三', '四', '五', '六', '七', '八', '九'];
|
|
|
+ return chineseNumber[number - 1];
|
|
|
+ } else {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ },
|
|
|
keyboardHeightChange(res) {
|
|
|
// #ifndef H5
|
|
|
console.log("this.danmuboxHeight",this.danmuboxHeight)
|
|
@@ -496,6 +506,10 @@
|
|
|
}
|
|
|
this.playTime = currentTime
|
|
|
}
|
|
|
+ if (Math.floor(e.detail.currentTime) != this.flagTime) {
|
|
|
+ this.flagTime = Math.floor(e.detail.currentTime)
|
|
|
+ this.checkDanmu()
|
|
|
+ }
|
|
|
},
|
|
|
changeTime(that,e) {
|
|
|
that.playDurationSeek = 0
|
|
@@ -529,6 +543,7 @@
|
|
|
},
|
|
|
fullscreenchange(event) {
|
|
|
this.isfull = event.detail.fullScreen
|
|
|
+ this.initTracks()
|
|
|
},
|
|
|
controlstoggle(event) {
|
|
|
this.crtShow = event.detail.show
|
|
@@ -1134,7 +1149,7 @@
|
|
|
},
|
|
|
// 发送弹幕
|
|
|
sendDanmu() {
|
|
|
- if(this.danmuIput==''||this.danmuIput.trim()=='') {
|
|
|
+ if(this.danmuIput=='') {
|
|
|
uni.showToast({
|
|
|
title: '弹幕不能为空',
|
|
|
icon: 'none'
|
|
@@ -1152,6 +1167,16 @@
|
|
|
text: item.content,
|
|
|
time: item.timePoint ? Number(item.timePoint) : this.playTime,
|
|
|
color: "#FFFFFF",
|
|
|
+ mode: item.mode|| "scroll",
|
|
|
+ top: null,
|
|
|
+ style: {
|
|
|
+ color: item.isColor==1 ? item.color || this.danmuItemStyle.color : this.danmuItemStyle.color,//是否彩色1是0否
|
|
|
+ fontSize: item.fontSize || this.danmuItemStyle.fontSize,
|
|
|
+ padding: this.danmuItemStyle.padding,
|
|
|
+ border:this.user.userId ==item.userId ? item.color ? `solid 1px ${item.color}`: this.danmuItemStyle.border : 'none',
|
|
|
+ borderRadius: this.user.userId==item.userId ? this.danmuItemStyle.borderRadius : 0,
|
|
|
+ backgroundColor: this.user.userId==item.userId ? this.danmuItemStyle.backgroundColor : 'transparent'
|
|
|
+ },
|
|
|
}))
|
|
|
} else {
|
|
|
this.danmuList = []
|
|
@@ -1196,7 +1221,7 @@
|
|
|
},
|
|
|
})
|
|
|
this.socket.onMessage((res) => {
|
|
|
- console.log("收到消息parse",JSON.parse(res.data))
|
|
|
+ // console.log("收到消息parse",JSON.parse(res.data))
|
|
|
const redata = JSON.parse(res.data);
|
|
|
if(redata.cmd=="heartbeat"){
|
|
|
//心跳
|
|
@@ -1226,7 +1251,6 @@
|
|
|
//重启
|
|
|
that.initSocket()
|
|
|
}
|
|
|
- // that.msgEnd = true
|
|
|
})
|
|
|
//监听socket错误
|
|
|
this.socket.onError((err) => {
|
|
@@ -1252,9 +1276,9 @@
|
|
|
content: this.danmuIput,
|
|
|
timePoint: this.playTime, // 弹幕对应视频时间节点()秒
|
|
|
platform: 'uniapp', //发送平台,app传值“app”,小程序传值“uniapp”
|
|
|
- fontSize: '14px',
|
|
|
+ fontSize: '16px',
|
|
|
mode: "scroll",
|
|
|
- color: "#fff",
|
|
|
+ color: "#ffffff",
|
|
|
};
|
|
|
this.socket.send({
|
|
|
data: JSON.stringify(data),
|
|
@@ -1264,7 +1288,6 @@
|
|
|
this.isSend = false;
|
|
|
},
|
|
|
fail: () => {
|
|
|
- console.log("发送失败")
|
|
|
uni.showToast({
|
|
|
title: '发送失败',
|
|
|
icon: 'none'
|
|
@@ -1280,19 +1303,113 @@
|
|
|
if (!this.player) {
|
|
|
this.player = uni.createVideoContext('video-content-box');
|
|
|
}
|
|
|
- this.player.sendDanmu({
|
|
|
+ // this.player.sendDanmu({
|
|
|
+ // text: content.content,
|
|
|
+ // color: "#FF0000",
|
|
|
+ // time: this.playTime + 1
|
|
|
+ // })
|
|
|
+ const id = content.userId +'_' + new Date().getTime()
|
|
|
+ const mystyle = {
|
|
|
+ color: content.color || this.danmuItemStyle.color,
|
|
|
+ fontSize: content.fontSize || this.danmuItemStyle.fontSize,
|
|
|
+ border: content.color ? `solid 1px ${content.color}`: this.danmuItemStyle.border,
|
|
|
+ borderRadius: this.danmuItemStyle.borderRadius,
|
|
|
+ padding: this.danmuItemStyle.padding,
|
|
|
+ backgroundColor: this.danmuItemStyle.backgroundColor
|
|
|
+ }
|
|
|
+ const otherstyle = {
|
|
|
+ color: content.color || this.danmuItemStyle.color,
|
|
|
+ fontSize: content.fontSize || this.danmuItemStyle.fontSize,
|
|
|
+ padding: this.danmuItemStyle.padding,
|
|
|
+ }
|
|
|
+ const mode = content.mode || "scroll"
|
|
|
+ const obj = {
|
|
|
+ id: content.id || id,
|
|
|
+ userId: content.userId,
|
|
|
text: content.content,
|
|
|
- color: "#FF0000",
|
|
|
- time: this.playTime + 1
|
|
|
+ time: this.flagTime + 1,
|
|
|
+ color: content.color || this.danmuItemStyle.color,
|
|
|
+ style: this.user.userId == content.userId ? mystyle : otherstyle,
|
|
|
+ top: null
|
|
|
+ }
|
|
|
+ console
|
|
|
+ if(this.showDanmu == 0) return
|
|
|
+ this.danmuList.push(obj)
|
|
|
+ },
|
|
|
+ initTracks() {
|
|
|
+ this.tracks = []
|
|
|
+ const trackHeight = 22; // 每行高度
|
|
|
+ const trackCount = 3
|
|
|
+ for (let i = 0; i < trackCount; i++) {
|
|
|
+ this.tracks.push({
|
|
|
+ top: i * trackHeight+10,
|
|
|
+ isFree: true
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取字体高度
|
|
|
+ getTextWidth(content) {
|
|
|
+ if (!this.ctx) {
|
|
|
+ this.ctx = uni.createCanvasContext('myCanvas')
|
|
|
+ }
|
|
|
+ const metrics = this.ctx.measureText(content)
|
|
|
+ return Math.ceil(metrics.width)
|
|
|
+ },
|
|
|
+ // 分配轨道
|
|
|
+ getFreeTrack(item) {
|
|
|
+ const width = this.getTextWidth(item.content)
|
|
|
+ const passWidth = width + uni.getSystemInfoSync().screenWidth
|
|
|
+ const duration = 8
|
|
|
+ for (let i = 0; i < this.tracks.length; i++) {
|
|
|
+ if (this.tracks[i].isFree) {
|
|
|
+ this.tracks[i].isFree = false;
|
|
|
+ // 等本条通过右边界的时间
|
|
|
+ let passtime = Math.ceil(duration * 1000 / passWidth * width)
|
|
|
+ passtime = passtime + 1000
|
|
|
+ // console.log("passtime==", passtime)
|
|
|
+ setTimeout(() => {
|
|
|
+ this.tracks[i].isFree = true;
|
|
|
+ }, passtime); // 5秒后释放轨道
|
|
|
+ return this.tracks[i].top;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 无可用轨道
|
|
|
+ if (item.userId == this.user.userId) {
|
|
|
+ let trackHeight = this.tracks[this.tracks.length - 1].top
|
|
|
+ return Math.random() * trackHeight + 16 // 自己发的弹幕随机高度; // 无可用轨道
|
|
|
+ } else {
|
|
|
+ // console.log("无可用轨道")
|
|
|
+ return 'abandon'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 检测并激活弹幕
|
|
|
+ checkDanmu() {
|
|
|
+ if(this.showDanmu == 0) return
|
|
|
+ // 筛选当前时间应出现的弹幕
|
|
|
+ const newDanmus = this.danmuList.filter((item) => Math.abs(item.time - this.flagTime) < 1)
|
|
|
+ // 分配轨道高度
|
|
|
+ newDanmus.forEach((item) => {
|
|
|
+ // 滚动弹幕随机高度
|
|
|
+ if(!item.top) {
|
|
|
+ item.top = this.getFreeTrack(item)
|
|
|
+ }
|
|
|
})
|
|
|
- // setTimeout(()=>{
|
|
|
- // this.player.sendDanmu({
|
|
|
- // text: content.content,
|
|
|
- // color: "#FF0000",
|
|
|
- // time: this.playTime
|
|
|
- // })
|
|
|
- // },100)
|
|
|
- }
|
|
|
+ // 过滤没有分配到空闲轨道弹幕
|
|
|
+ const aliveNewDanmus = newDanmus.filter((item) => item.top != 'abandon')
|
|
|
+ // 添加到活跃列表
|
|
|
+ this.activeDanmus = [...this.activeDanmus, ...aliveNewDanmus]
|
|
|
+ },
|
|
|
+ animationend(moveItem, i) {
|
|
|
+ // 移除动画结束的弹幕(性能优化)
|
|
|
+ this.activeDanmus = this.activeDanmus.filter((item) => item.id != moveItem.id)
|
|
|
+ },
|
|
|
+ switchDanmu() {
|
|
|
+ this.showDanmu = this.showDanmu == 1 ? 0:1
|
|
|
+ if(this.showDanmu == 0) {
|
|
|
+ this.activeDanmus = []
|
|
|
+ this.initTracks()
|
|
|
+ }
|
|
|
+ },
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
@@ -1996,7 +2113,7 @@
|
|
|
}
|
|
|
.danmuPopup {
|
|
|
background-color: #fff;
|
|
|
- padding-bottom: var(--window-bottom);
|
|
|
+ padding-bottom: calc(var(--window-bottom) + 10px);
|
|
|
&-head {
|
|
|
width: 100%;
|
|
|
padding: 10px;
|
|
@@ -2041,5 +2158,41 @@
|
|
|
color: #757575;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ .danmu-item {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ white-space: nowrap;
|
|
|
+ font-size: 16px;
|
|
|
+ height: 20px;
|
|
|
+ display: inline-flex;
|
|
|
+ box-sizing: border-box;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .danmuMove {
|
|
|
+ // animation: mymove 8s linear forwards;
|
|
|
+ // animation-duration: 8s;
|
|
|
+ animation-timing-function: linear;
|
|
|
+ animation-delay: 0s;
|
|
|
+ animation-iteration-count: 1;
|
|
|
+ animation-direction: normal;
|
|
|
+ animation-fill-mode: forwards;
|
|
|
+ animation-play-state: running;
|
|
|
+ animation-name: mymove;
|
|
|
+ will-change: transform;
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes mymove {
|
|
|
+ from {
|
|
|
+ transform: translateX(100vw);
|
|
|
+ }
|
|
|
+
|
|
|
+ to {
|
|
|
+ transform: translateX(-100%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .danmu-icon{
|
|
|
+ height: 24px;
|
|
|
+ width: 24px;
|
|
|
+ margin-right: 12px;
|
|
|
+ }
|
|
|
</style>
|