和发视频的时候,往往需要同时上传视频缩略图。最近应产品经理的要求,需要一个发布视频动态的功能。我的第一反应是H5的标签vidio和canvas,这里是完成这个功能的过程:首先,总体思路是创建一个vidio,然后创建一个canvas和一个画笔,调用画笔的drawImage方法,使用vidio作为参数,图像将绘制为视频的缩略图。事不宜迟,代码:functioncreatImg(){constvideo=document.getElementById('videoPreview');constcanvas=document.createElement('canvas');constctx=canvas.getContext('2d');constimgHeight=video.videoHeight;constimgWidth=video.videoWidth;ctx.drawImage(视频,0,0,imgWidth,imgHeight);constimgSrc=canvas.toDataURL('image/png');console.log(imgSrc);}这个方法是在上传视频发送ajax成功的回调函数中调用的,//上传视频$('#video').on('change',(e)=>{constvideo=e.currentTarget.files[0];constformData=newFormData();formData.append('file',video);$.ajax({url:videourl,crossDomain:true,data:formData,dataType:'json',method:'POST',contentType:false,processData:false,timeout:0,}).done((jsonData)=>{//设置视频标签的src操作setTimeout(()=>{creatImg();},500);}).fail(()=>{layer.alert('上传失败',{shift:5});})});这样就完成了功能……开玩笑的,怎么能让你心情好一点?运行后报如下bug:这个bug的意思是dirtycanvas不会被导入。出现这个问题的原因是canvas中引用的video对象跨域,从而污染了canvas。解决问题的方法是在canvas中引入一个本地视频对象,其实很简单。改变creatImage引用的位置,从类型文件的输入标签数组中获取视频对象。这里的video对象是本地的,所以不会出现跨域现象,如下上面代码显示:$('#video').on('change',(e)=>{constvideo=e.currentTarget.files[0];creatImg(video);//constvideoName=video.name;constformData=newFormData();formData.append('file',video);constindex=layer.load(2);$.ajax({url:`${upload_url}/toServer`,crossDomain:true,data:formData,dataType:'json',method:'POST',contentType:false,processData:false,timeout:0,}).done((jsonData)=>{//这个和视频操作的src属性值有关}).fail(()=>{layer.alert('uploadfailed',{shift:5});})});constvideo=e.currentTarget.files[0];这里的视频是本地视频对象,接下来我们对creatImg函数进行优化,如下代码所示:video.addEventListener('加载edmetadata',functionloadedmetadata(){setTimeout(()=>{constcanvas=document.createElement('canvas');canvas.width=this.videoWidth;canvas.height=this.videoHeight;constctx=canvas.getContext('2d');ctx.drawImage(this,0,0);constimage=newImage();image.src=canvas.toDataURL('image/png');image.onload(()=>{constformData=newFormData();formData.append('file',dataURItoBlob(canvas.toDataURL('image/png')),`${+newDate()}.png`);$.ajax({url:upload_url,crossDomain:true,data:formData,dataType:'json',method:'POST',contentType:false,processData:false,}).done((jsonData)=>{//.....//Will该值存储在id为thumbnail的input标签的value属性中constbody=jsonData.body;$('#thumbnail').val(body);}).fail(()=>{layer.alert('上传失败');});});},300);},错误的);video.src=URL.createObjectURL(stream);video.play();}创建画布,创建画笔,传入video对象绘制图片,这一系列的操作都是在视频加载完成后完成的,所以所有操作都在监听的loademetadata的回调函数中完成视频。图片绘制完成后,需要将图片上传到服务器,通过FormData对象ajax生成。发送到服务器的名称:值键值对。向FormData添加键值对时,调用append方法。append方法的第一个参数是字段名,第二个参数是字段值。这里的字段值是一个Blob对象,第三个参数是文件名。这里创建Blob的方法是dataURItoBlob方法,如下代码所示,因为canvas.toDataURL方法返回的是图片的Base64编码,所以这个函数的作用是将Base64编码的Blob对象进行转换,具体过程如代码所示:functiondataURItoBlob(dataURI){constbinary=atob(dataURI.split(',')[1]);常量数组=[];for(leti=0;i
