videoBox.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <template>
  2. <view class="video-wrap" @click="handleClickWrap">
  3. <video
  4. autoplay
  5. object-fit="contain"
  6. show-mute-btn
  7. show-background-playback-button
  8. enable-play-gesture
  9. :poster="videoInfo.cover_img_url"
  10. :src="videoInfo.video_url"
  11. :id="videoInfo.community_video_id"
  12. @ended="handleVideoEnd"
  13. @pause="handleVideoPause"
  14. @timeupdate="handleTimeUpdate"
  15. v-if="videoInfo.id==curVideoId"
  16. >
  17. <view class="video-inner-right-box">
  18. <view class="video-speed-btn" @click.stop="showSpeedOpt=true">倍速</view>
  19. </view>
  20. <!-- 倍速选项模块 -->
  21. <view class="speed-opt-box" v-if="showSpeedOpt">
  22. <view
  23. class="item"
  24. :style="{color:item==curSpeed?'#F3A52F':''}"
  25. v-for="item in speedOpts"
  26. :key="item"
  27. @click.stop="handleVideoSpeedChange(item)"
  28. >{{item}}X</view>
  29. </view>
  30. </video>
  31. <image @click="handelClickPlay" v-else class="poster" :src="videoInfo.cover_img_url" mode="aspectFill" lazy-load/>
  32. <!-- 外面弹幕按钮 -->
  33. <view class="danmu-btn-box" v-if="showDanmu">
  34. <view class="big-box" v-if="!closeDM">
  35. <view class="left" @click.stop="showInput=true"></view>
  36. <view class="right" @click.stop="closeDM=true"></view>
  37. </view>
  38. <view class="small-box" v-else @click.stop="closeDM=false"></view>
  39. </view>
  40. <!-- 弹幕输入弹窗 -->
  41. <view class="flex danmu-input-box" v-if="showInput">
  42. <view class="flex input-box">
  43. <input
  44. type="text"
  45. v-model="danmuText"
  46. placeholder="请输入弹幕~"
  47. cursor-spacing="20"
  48. maxlength="50"
  49. focus
  50. confirm-type="send"
  51. @keyboardheightchange="keyboardheightchange"
  52. />
  53. <text>{{danmuText.length}}/50</text>
  54. </view>
  55. <view class="btn">发送</view>
  56. </view>
  57. </view>
  58. </template>
  59. <script>
  60. export default {
  61. props:{
  62. showDanmu:{
  63. type:Boolean,
  64. default:false
  65. },//是否显示弹幕
  66. videoInfo:{},//{source:2-视频社区\3-路演视频,id:视频社区id\路演视频id,...其他数据}
  67. curVideoId:0,//当前正在播放的id
  68. },
  69. watch: {
  70. curVideoId(){
  71. this.curSpeed='1.0'
  72. }
  73. },
  74. data() {
  75. return {
  76. curVideoIns:null,
  77. showInput:false,//显示悬浮输入弹幕弹窗
  78. closeDM:false,//是否关闭弹幕
  79. danmuText:'',
  80. showSpeedOpt:false,
  81. speedOpts:['0.5','0.8','1.0','1.25','1.5','2.0'],
  82. curSpeed:'1.0',
  83. }
  84. },
  85. methods: {
  86. //点击最外层盒子
  87. handleClickWrap(){
  88. this.showSpeedOpt=false
  89. },
  90. // 点击播放
  91. handelClickPlay(){
  92. this.$emit('videoPlay', this.videoInfo)
  93. setTimeout(() => {
  94. this.curVideoIns=uni.createVideoContext(this.curVideoId.toString(),this)//由于是在自定义组件内 所有this不可少
  95. }, 300);
  96. },
  97. handleVideoEnd(){
  98. // 此处因为如果不调用退出全屏方法 安卓和ios页面均会表现异常,安卓横屏不恢复竖屏,ios底部tabbar渲染异常
  99. this.curVideoIns.exitFullScreen()
  100. this.curVideoIns=null
  101. this.$emit('ended')
  102. },
  103. handleVideoPause(){
  104. this.$emit('pause')
  105. },
  106. handleTimeUpdate(e){
  107. this.$emit('timeupdate',e)
  108. },
  109. //键盘高度变为0 则收起悬浮弹幕输入框
  110. keyboardheightchange(e){
  111. if(e.detail.height===0){
  112. setTimeout(() => {
  113. this.showInput=false
  114. }, 60);
  115. }
  116. },
  117. // 倍速切换
  118. handleVideoSpeedChange(item){
  119. const num=Number(item)
  120. this.curVideoIns.playbackRate(num)
  121. this.curSpeed=item
  122. this.showSpeedOpt=false
  123. }
  124. },
  125. }
  126. </script>
  127. <style lang="scss" scoped>
  128. .video-wrap{
  129. width: 100%;
  130. height: 100%;
  131. position: relative;
  132. video,.poster{
  133. width: 100%;
  134. height: 100%;
  135. border-radius: 20rpx;
  136. position: relative;
  137. }
  138. .poster{
  139. position: relative;
  140. &::after{
  141. content:'';
  142. display: block;
  143. position: absolute;
  144. width: 120rpx;
  145. height: 120rpx;
  146. top: 50%;
  147. left: 50%;
  148. transform: translate(-50%,-50%);
  149. background-image: url('@/static/video-play-btn.png');
  150. background-size: cover;
  151. }
  152. }
  153. .danmu-btn-box{
  154. position: absolute;
  155. bottom: -70rpx;
  156. right: 6rpx;
  157. .big-box{
  158. width: 248rpx;
  159. height: 50rpx;
  160. background-image: url('@/static/danmu-show-btn.png');
  161. background-size: cover;
  162. display: flex;
  163. .left{
  164. width: 67%;
  165. height: 100%;
  166. flex-shrink: 0;
  167. }
  168. .right{
  169. flex: 1;
  170. height: 100%;
  171. }
  172. }
  173. .small-box{
  174. width: 80rpx;
  175. height: 50rpx;
  176. background-image: url('@/static/danmu-close-btn.png');
  177. background-size: cover;
  178. }
  179. }
  180. .danmu-input-box{
  181. position: fixed;
  182. left: 0;
  183. right: 0;
  184. bottom: 0;
  185. z-index: 999999;
  186. background-color: #fff;
  187. padding: 10rpx 34rpx;
  188. border-top: 1px solid #E5E5E5;
  189. align-content: center;
  190. .input-box{
  191. flex:1;
  192. border-radius: 40rpx;
  193. padding: 6rpx 10rpx;
  194. background: #EFEFEF;
  195. border: 2rpx solid #E5E5E5;
  196. align-items: center;
  197. font-size: 12px;
  198. input{
  199. flex:1;
  200. }
  201. text{
  202. color: #999;
  203. }
  204. }
  205. .btn{
  206. width: 100rpx;
  207. flex-shrink: 0;
  208. color: #F3A52F;
  209. font-size: 12px;
  210. display: flex;
  211. align-items: center;
  212. justify-content: center;
  213. }
  214. }
  215. .video-inner-right-box{
  216. position: absolute;
  217. bottom: 30%;
  218. right: 5%;
  219. }
  220. .video-speed-btn{
  221. width: 80rpx;
  222. height: 44rpx;
  223. display: flex;
  224. align-items: center;
  225. justify-content: center;
  226. background: rgba(0, 0, 0, 0.4);
  227. border-radius: 22rpx;
  228. color: #fff;
  229. font-size: 12px;
  230. }
  231. .speed-opt-box{
  232. position: absolute;
  233. right: 0;
  234. top: 0;
  235. bottom: 0;
  236. width: 20%;
  237. background: rgba(0, 0, 0, 0.8);
  238. display: flex;
  239. flex-direction: column;
  240. justify-content: space-around;
  241. padding-top: 55rpx;
  242. .item{
  243. color: #fff;
  244. font-size: 26rpx;
  245. flex: 1;
  246. width: 100%;
  247. text-align: center;
  248. }
  249. }
  250. }
  251. </style>