• 2020-02-19
    前两天想说练一下vue,就按照bilibili写了一个demo(我第一次放这种模仿的页面,如果有哪里不合适的请告诉我哈),就写了比较核心的首页和视频播放页,包括控制视频和弹幕渲染等等的,记录一下。



先放一下最终效果

在这里插入图片描述
因为当时做的时候为了追求效果打的真实的名字,就手动打了一下码


一、vue控制视频播放


1. 引入视频

这个非常简单,就不用我说了吧~

<video id="video" src="video/video-horizontal.mp4" ref="video">
	您的浏览器不支持 video 标签。
</video>

2. 播放 / 暂停功能

因为没有我们想手动控制视频的暂停或者播放,所以没有加自动播放属性,并且我们要绑定事件来控制视频。

<!-- 开始 / 暂停按钮 -->
<div class="play" @click="playOrPause()">
	<img v-if="!isPlay" src="img/goPlay.png" />
	<img v-cloak v-else src="img/pause.png" />
</div>
//  开始/ 暂停事件
  	playOrPause: function(){
  		if(this.isPlay){
  			$("#video").trigger("pause");
  		}else{
  			$("#video").trigger("play");	
  		}
  		this.isPlay = !this.isPlay;
  	}

没有加自动播放属性的视频默认情况下是在暂停状态的,所以isPlay的默认值是false。

data: {
   	isPlay: false
}

3. 获取并及时更新视频时间
//  获取总时长
   	videoCanPlay: function(){
	    var duration =this.$refs.video.duration;
	    this.vcTotalTime = this.getFormatVideoTime(duration);
   	},
//  更新进度时间
   	videoTimeUpdate: function(){
	   	var currTime =this.$refs.video.currentTime;
	   	var duration =this.$refs.video.duration;
	   	this.vcCurrentTime = this.getFormatVideoTime(currTime);
	   	var pre = currTime / duration;
	   	this.vcProgress = pre*100;
   	},
//  格式化时间
   	getFormatVideoTime: function(time) {
           var time = time;
           var m = parseInt(time%3600/60),
               s = parseInt(time%60);
           m = m < 10 ? "0"+m : m;
           s = s < 10 ? "0"+s : s;
           return m+":"+s;
	}
<video id="video"  src="video/video-horizontal.mp4" ref="video"
	   @canplay="videoCanPlay()" 
	   @timeupdate="videoTimeUpdate()" >
	您的浏览器不支持 video 标签。
</video>

然后在进度条和时间上也要展示最新的状态,所以这里也绑定上。

<div class="progress">
	<span class="alreadyRead" :style="{width: vcProgress*100/100 +'%'}"></span>
	<img @mousedown="move" :style="{left: vcProgress*100/100 +'%'}" src="img/progress.png" />
	<span class="unRead"></span>
</div>
<p v-cloak class="time">{{ vcCurrentTime }} / {{ vcTotalTime }}</p>

这里绑定的move事件是用来拖动进度条调整时间的。
(另外在电脑上模拟手机端测试的话是不好用的,测试的话要切成PC才可以,这里贴一下供大家参考哈。)

//  拖动进度条
    move(e){
      	let odiv = e.target;    //获取目标元素
      	//算出鼠标相对元素的位置
      	let disX = e.clientX - odiv.offsetLeft;
      	let disY = e.clientY - odiv.offsetTop;
      	document.onmousemove = (e)=>{    //鼠标按下并移动的事件
	        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
	        let left = e.clientX - disX;  
	        let top = e.clientY - disY;
	        //绑定元素位置到positionX和positionY上面
	        this.positionX = top;
	        this.positionY = left;
	        //移动当前元素
	        odiv.style.left = left + 'px';
	        odiv.style.top = top + 'px';
      	};
      	document.onmouseup = (e) => {
	        document.onmousemove = null;
	        document.onmouseup = null;
      	};
    }

4. 播放完成 / 重放

播放完成后的效果图先贴一下

在这里插入图片描述

//	播放完成
	videoEnd: function(){
		$(".player-ended").css('display',"flex");
	},
//	重播
	replay: function(){
		$(".player-ended").hide();
		$("#video").trigger("play");
	}

重播按钮上直接绑定replay就可以了,播放完成这样绑定

<video id="video"  src="video/video-horizontal.mp4" ref="video"
	   @canplay="videoCanPlay()" 
	   @timeupdate="videoTimeUpdate()" 
	   @ended="videoEnd()">
	您的浏览器不支持 video 标签。
</video>


二、弹幕功能


1. 添加弹幕容器

容器和video相对定位就可以了,就不贴代码了。

<div class="player-barrage">
	<ul class="roll"></ul>
	<ul class="center"></ul>
</div>

2. 弹幕列表

这里的弹幕分为滚动和居中两种,
一般来说应该是在初始化的时候在接口获取的,我这里自己练习,就写成固定的了。
canAdd:用来判断是否已经添加过了,已经添加过的弹幕不再重复添加了。
time:弹幕出现时间。
color:弹幕颜色。
cont:弹幕内容。

data:{
   	rollBarrageIndex: 0,		//用来固定位置的
   	rollBarrageList:[{		//滚动弹幕
   		canAdd: true,
   		time: '00:00',
   		color: '#fcf044',
   		cont: '1测试弹幕测试幕测试弹幕测试弹幕1'
   	},{
   		canAdd: true,
   		time: '00:00',
   		color: '#ffffff',
   		cont: '11测试弹幕测试弹幕测试弹幕幕测试弹幕测试弹幕测试弹幕测试弹幕测试弹幕1'
   	}],
    	
   	centerBarrageIndex: 0,
   	centerBarrageList:[{		//顶部居中弹幕
   		canAdd: true,
   		time: '00:00',
   		color: '#ffffff',
   		cont: '00000000000000000000000'
   	},{
   		canAdd: true,
   		time: '00:00',
   		color: '#e82624',
   		cont: '1111111111111111111111111111111111111111111111111'
   	}]
}

3. 在页面中渲染弹幕

在这里先说下哈,bilibili的APP的弹幕相关功能真的是很非常完善的,要是用H5做很麻烦,
比如暂停视频时弹幕应该也跟随暂停,这个功能使用canvas更方便做出来,
在这里因为只是练习demo,弹幕的动效和渲染我都是用定时器做的,没办法完成到对应暂停,只做了些基础的功能。

//	更新滚动弹幕
    updataRollBarrage: function(){
   		var _this = this;
   		$(_this.rollBarrageList).each(function(i,item){
   			//当符合出现弹幕时间,并且弹幕没有被添加过时,添加弹幕
   			if(item.time == _this.vcCurrentTime && item.canAdd){
   				//弹幕要固定top是因为清除已经展示过的弹幕会让后面的弹幕往上移
   				$(".player-barrage .roll").append("<li style='top: " + _this.rollBarrageIndex*21 + "px; color: " + item.color + ";'><p>" + item.cont + "</p></li>");
   				//选中当前添加的弹幕
   				var obj = $(".player-barrage .roll li").last();
   				//当前弹幕匀速向左移动
   				var speed = obj.width() * 7;
   				$(obj).find('p').animate({left:"-100%"}, speed, "linear",function(){
   					//这个时候弹幕已经跟屏幕左对齐了,然后再让父元素移出屏幕
   					//不用之前的speed是为了和之前的速度保持一致
   					var speedBox = $(obj).parent().width() * 7; 
   					$(obj).animate({left:"0%"}, speedBox, "linear",function(){
   						//父元素也移出屏幕后,可以清除当前弹幕
   						$(obj).remove();       						
   					})
   				});
   				//我这里是默认展示五行滚动弹幕
   				//如果想根据同一时间弹幕数量的多少决定展示几行弹幕,可以添加当前时间的判断,但是在demo里面我就不写这么复杂了
   				_this.rollBarrageIndex = (_this.rollBarrageIndex >= 4) ? (_this.rollBarrageIndex - 4) : (_this.rollBarrageIndex + 1);
   				//已添加过的弹幕不再添加了
   				item.canAdd = false;
   				//终止each循环
   				return false;
   			}
   		})
   	},
//	更新居中弹幕
    updataCenterBarrage: function(){
    	//大部分逻辑和滚动弹幕一样,动效直接在css里面写,所以这里只要定时清除就可以了
   		var _this = this;
   		$(_this.centerBarrageList).each(function(i,item){
   			if(item.time == _this.vcCurrentTime && item.canAdd){
   				$(".player-barrage .center").append("<li style='top: " + _this.centerBarrageIndex*21 + "px; color: " + item.color + ";'><p>" + item.cont + "</p></li>");
   				var obj = $(".player-barrage .center li").last();
   				//我这里设置3秒后自动清除
   				//如果想根据内容多少来判断展示时间,获取一下宽度,乘以一个系数就可以了,别忘了设置最短时间
				setTimeout(function(){
 						$(obj).remove(); 
				},3000)
   				_this.centerBarrageIndex = (_this.centerBarrageIndex >= 4) ? (_this.centerBarrageIndex - 4) : (_this.centerBarrageIndex + 1);
   				item.canAdd = false;
   				return false;
   			}
   		})
   	}

然后这两个方法都在更新进度时间中调用就可以了

//  更新进度时间
   	videoTimeUpdate: function(){
    	var currTime =this.$refs.video.currentTime;
    	var duration =this.$refs.video.duration;
    	this.vcCurrentTime = this.getFormatVideoTime(currTime);
    	var pre = currTime / duration;
    	this.vcProgress = pre*100;
    	//调用渲染弹幕方法
    	this.updataRollBarrage();
    	this.updataCenterBarrage();
	}

然后在重放的时候,也别忘了重新设置可以被添加

//	重播
	replay: function(){
		console.log("replay");
		$(".player-ended").hide();
		$("video").trigger("play");	
		//清除当前屏幕上的弹幕
		$(".player-barrage li").remove();
		//可重新添加弹幕
		$(this.rollBarrageList).each(function(i,item){
			item.canAdd = true;
		})
		$(this.centerBarrageList).each(function(i,item){
			item.canAdd = true;
		})
	}


Logo

前往低代码交流专区

更多推荐