摘要:發(fā)布視頻時候,經(jīng)常需要上傳同時上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個發(fā)布視頻動態(tài)的功能,我第一反應(yīng)就想到了的標簽和,在這里記錄下我完成該功能的過程首先,整體思路是創(chuàng)建一個,然后創(chuàng)建一個和一個畫筆,調(diào)用畫筆的方法,將作為參數(shù),
發(fā)布視頻時候,經(jīng)常需要上傳同時上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個發(fā)布視頻動態(tài)的功能,我第一反應(yīng)就想到了H5的標簽vidio和canvas,在這里記錄下我完成該功能的過程:
首先,整體思路是創(chuàng)建一個vidio,然后創(chuàng)建一個canvas和一個畫筆,調(diào)用畫筆的drawImage方法,將vidio作為參數(shù),就會畫出該視頻的縮略圖。
二話不說擼代碼:
function creatImg() { const video = document.getElementById("videoPreview"); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const imgHeight = video.videoHeight; const imgWidth = video.videoWidth; ctx.drawImage(video, 0, 0, imgWidth, imgHeight); const imgSrc = canvas.toDataURL("image/png"); console.log(imgSrc); }
該方法是在上傳視頻發(fā)送ajax成功的回調(diào)函數(shù)中調(diào)用的,
// 上傳視頻 $("#video").on("change", (e) => { const video = e.currentTarget.files[0]; const formData = new FormData(); formData.append("file", video); $.ajax({ url: videourl, crossDomain: true, data: formData, dataType: "json", method: "POST", contentType: false, processData: false, timeout: 0, }).done((jsonData) => { //設(shè)置video標簽的src操作 setTimeout(() => { creatImg(); }, 500); }).fail(() => { layer.alert("上傳失敗", { shift: 5 }); }) });
這樣就完成這個功能了......開玩笑,怎么能讓你好過?運行后報了如下bug:
這個bug的意思是:臟的canvas不會被引入,出現(xiàn)這個問題的原因是canvas中引用的視頻對象跨域了,從而污染了canvas,解決問題的方法是在canvas中引入本地的視頻對象,其實做法很簡單,改變一下creatImage引用的位置,在類型為file的input標簽數(shù)組中取到video對象,這里的video對象是本地的,從而不會出現(xiàn)跨域的現(xiàn)象,如下面代碼所示:
$("#video").on("change", (e) => { const video = e.currentTarget.files[0]; creatImg(video); // const videoName = video.name; const formData = new FormData(); formData.append("file", video); const index = layer.load(2); $.ajax({ url: `${upload_url}/toServer`, crossDomain: true, data: formData, dataType: "json", method: "POST", contentType: false, processData: false, timeout: 0, }).done((jsonData) => { //這是video的src屬性值的相關(guān)操作 }).fail(() => { layer.alert("上傳失敗", { shift: 5 }); }) });
const video = e.currentTarget.files[0];這里的video是本地的video對象,接下來,我們優(yōu)化一下creatImg函數(shù),如下代碼所示:
function creatImg(stream) { const video = document.createElement("video"); video.addEventListener("loadedmetadata", function loadedmetadata() { setTimeout(() => { const canvas = document.createElement("canvas"); canvas.width = this.videoWidth; canvas.height = this.videoHeight; const ctx = canvas.getContext("2d"); ctx.drawImage(this, 0, 0); const image = new Image(); image.src = canvas.toDataURL("image/png"); image.onload(() => { const formData = new FormData(); formData.append("file", dataURItoBlob(canvas.toDataURL("image/png")), `${+new Date()}.png`); $.ajax({ url: upload_url, crossDomain: true, data: formData, dataType: "json", method: "POST", contentType: false, processData: false, }).done((jsonData) => { //..... //將值存儲在id為thumbnail的input標簽當中的value屬性當中 const body = jsonData.body; $("#thumbnail").val(body); }).fail(() => { layer.alert("上傳失敗"); }); }); }, 300); }, false); video.src = URL.createObjectURL(stream); video.play(); }
創(chuàng)建canvas,創(chuàng)建畫筆,將video對象傳入畫出圖片,這一系列操作都是在video加載之后完成的,所以,所有操作都在video監(jiān)聽的loademetadata的回調(diào)函數(shù)當中完成的,在圖片畫好以后需要將該圖片上傳到服務(wù)器,通過FormData對象來生成用于ajax向服務(wù)器發(fā)送的name:value的鍵值對,在給FormData添加鍵值對是調(diào)用append方法,append方法的第一個參數(shù)字段名,第二個參數(shù)是字段值,這里的字段值是一個Blob對象,第三個參數(shù)是文件名稱,這里創(chuàng)建Blob的方法是 dataURItoBlob方法,如下面代碼所示,因為canvas.toDataURL的方法返回的是圖片的Base64的編碼,所以這個函數(shù)的作用就是將Base64的編碼轉(zhuǎn)換成Blob對象,具體過程如代碼所示:
function dataURItoBlob(dataURI) { const binary = atob(dataURI.split(",")[1]); const array = []; for (let i = 0; i < binary.length; i += 1) { array.push(binary.charCodeAt(i)); } return new Blob([new Uint8Array(array)], { type: "image/png" }); }
這里首先調(diào)用window的atob的方法,將被編譯成的Base64的數(shù)據(jù)解碼成二進制的數(shù)據(jù),接下來調(diào)用binary對象的charCodeAt方法來將制定位置上的二進制數(shù)據(jù)進行unicode編碼,并把所有的編碼后的數(shù)據(jù)存儲在數(shù)組當中,最后根據(jù)這個數(shù)組創(chuàng)建一個Unit8Array的對象,該對象是無符號8位整數(shù),因為初始化Blob時的第一個參數(shù)必須是數(shù)組,所以要把這個8位無符號整數(shù)存放在數(shù)組當中。
總結(jié):在完成這個功能的過程中涉及道幾個重要的知識點,羅列在下面,我將在后面的相關(guān)文章當中逐一具體介紹:
1、canvas的video必須是同域的,如果video跨域了,那么將會污染canvas
2、在向服務(wù)器發(fā)送圖片的時候,需要用到幾個重要的對象和方法
FormData對象:可以讓XMLHttpRequest發(fā)送鍵值對組成的對象
window.atob方法:將Base64的數(shù)據(jù)解碼成二進制的數(shù)據(jù)
binary.charCodeAt方法:將二進制的數(shù)據(jù)進行unicode編碼
Uint8Array對象:通過傳入的數(shù)組創(chuàng)建一個無符號的八位整數(shù)
Blob對象:不可變的,原始數(shù)據(jù)的類似文件對象
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/11022.html
摘要:明白模塊化模塊化就是將一個大的功能拆分為多個塊,每一個塊都是獨立的,你不需要去擔心污染全局變量,命名沖突什么的。目前最重要的應(yīng)用場景之一,就是在的握手階段,客戶端服務(wù)端利用算法交換對稱密鑰。 1、應(yīng)用canvas獲取video的縮略圖 發(fā)布視頻時候,經(jīng)常需要上傳同時上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個發(fā)布視頻動態(tài)的功能,我第一反應(yīng)就想到了H5的標簽vidio和canv...
摘要:明白模塊化模塊化就是將一個大的功能拆分為多個塊,每一個塊都是獨立的,你不需要去擔心污染全局變量,命名沖突什么的。目前最重要的應(yīng)用場景之一,就是在的握手階段,客戶端服務(wù)端利用算法交換對稱密鑰。 1、應(yīng)用canvas獲取video的縮略圖 發(fā)布視頻時候,經(jīng)常需要上傳同時上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個發(fā)布視頻動態(tài)的功能,我第一反應(yīng)就想到了H5的標簽vidio和canv...
摘要:函數(shù)式編程術(shù)語大全函數(shù)式編程有許多優(yōu)點,它也越來越流行了。然而,每個編程范式都有自己獨特的術(shù)語,函數(shù)式編程也不例外。作用域有兩種類似全局作用域和局部作用域。目前最重要的應(yīng)用場景之一,就是在的握手階段,客戶端服務(wù)端利用算法交換對稱密鑰。 1、JavaScript 函數(shù)式編程術(shù)語大全 函數(shù)式編程(FP)有許多優(yōu)點,它也越來越流行了。然而,每個編程范式都有自己獨特的術(shù)語,函數(shù)式編程也不例外。...
閱讀 3169·2021-11-22 15:29
閱讀 1830·2021-10-12 10:11
閱讀 1889·2021-09-04 16:45
閱讀 2440·2021-08-25 09:39
閱讀 2856·2021-08-18 10:20
閱讀 2613·2021-08-11 11:17
閱讀 508·2019-08-30 12:49
閱讀 3389·2019-08-30 12:49