成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

應(yīng)用canvas獲取video的縮略圖

edagarli / 802人閱讀

摘要:發(fā)布視頻時(shí)候,經(jīng)常需要上傳同時(shí)上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個(gè)發(fā)布視頻動(dòng)態(tài)的功能,我第一反應(yīng)就想到了的標(biāo)簽和,在這里記錄下我完成該功能的過程首先,整體思路是創(chuàng)建一個(gè),然后創(chuàng)建一個(gè)和一個(gè)畫筆,調(diào)用畫筆的方法,將作為參數(shù),

發(fā)布視頻時(shí)候,經(jīng)常需要上傳同時(shí)上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個(gè)發(fā)布視頻動(dòng)態(tài)的功能,我第一反應(yīng)就想到了H5的標(biāo)簽vidio和canvas,在這里記錄下我完成該功能的過程:
首先,整體思路是創(chuàng)建一個(gè)vidio,然后創(chuàng)建一個(gè)canvas和一個(gè)畫筆,調(diào)用畫筆的drawImage方法,將vidio作為參數(shù),就會(huì)畫出該視頻的縮略圖。

二話不說擼代碼:

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標(biāo)簽的src操作
      setTimeout(() => {
        creatImg();
      }, 500);
    }).fail(() => {
      layer.alert("上傳失敗", { shift: 5 });
    })
  });

這樣就完成這個(gè)功能了......開玩笑,怎么能讓你好過?運(yùn)行后報(bào)了如下bug:

這個(gè)bug的意思是:臟的canvas不會(huì)被引入,出現(xiàn)這個(gè)問題的原因是canvas中引用的視頻對(duì)象跨域了,從而污染了canvas,解決問題的方法是在canvas中引入本地的視頻對(duì)象,其實(shí)做法很簡(jiǎn)單,改變一下creatImage引用的位置,在類型為file的input標(biāo)簽數(shù)組中取到video對(duì)象,這里的video對(duì)象是本地的,從而不會(huì)出現(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對(duì)象,接下來,我們優(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) => {
          //.....
          //將值存儲(chǔ)在id為thumbnail的input標(biāo)簽當(dāng)中的value屬性當(dāng)中
          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對(duì)象傳入畫出圖片,這一系列操作都是在video加載之后完成的,所以,所有操作都在video監(jiān)聽的loademetadata的回調(diào)函數(shù)當(dāng)中完成的,在圖片畫好以后需要將該圖片上傳到服務(wù)器,通過FormData對(duì)象來生成用于ajax向服務(wù)器發(fā)送的name:value的鍵值對(duì),在給FormData添加鍵值對(duì)是調(diào)用append方法,append方法的第一個(gè)參數(shù)字段名,第二個(gè)參數(shù)是字段值,這里的字段值是一個(gè)Blob對(duì)象,第三個(gè)參數(shù)是文件名稱,這里創(chuàng)建Blob的方法是 dataURItoBlob方法,如下面代碼所示,因?yàn)閏anvas.toDataURL的方法返回的是圖片的Base64的編碼,所以這個(gè)函數(shù)的作用就是將Base64的編碼轉(zhuǎn)換成Blob對(duì)象,具體過程如代碼所示:

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ù)解碼成二進(jìn)制的數(shù)據(jù),接下來調(diào)用binary對(duì)象的charCodeAt方法來將制定位置上的二進(jìn)制數(shù)據(jù)進(jìn)行unicode編碼,并把所有的編碼后的數(shù)據(jù)存儲(chǔ)在數(shù)組當(dāng)中,最后根據(jù)這個(gè)數(shù)組創(chuàng)建一個(gè)Unit8Array的對(duì)象,該對(duì)象是無符號(hào)8位整數(shù),因?yàn)槌跏蓟疊lob時(shí)的第一個(gè)參數(shù)必須是數(shù)組,所以要把這個(gè)8位無符號(hào)整數(shù)存放在數(shù)組當(dāng)中。

總結(jié):在完成這個(gè)功能的過程中涉及道幾個(gè)重要的知識(shí)點(diǎn),羅列在下面,我將在后面的相關(guān)文章當(dāng)中逐一具體介紹:
1、canvas的video必須是同域的,如果video跨域了,那么將會(huì)污染canvas
2、在向服務(wù)器發(fā)送圖片的時(shí)候,需要用到幾個(gè)重要的對(duì)象和方法

FormData對(duì)象:可以讓XMLHttpRequest發(fā)送鍵值對(duì)組成的對(duì)象

window.atob方法:將Base64的數(shù)據(jù)解碼成二進(jìn)制的數(shù)據(jù)

binary.charCodeAt方法:將二進(jìn)制的數(shù)據(jù)進(jìn)行unicode編碼

Uint8Array對(duì)象:通過傳入的數(shù)組創(chuàng)建一個(gè)無符號(hào)的八位整數(shù)

Blob對(duì)象:不可變的,原始數(shù)據(jù)的類似文件對(duì)象

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/11022.html

相關(guān)文章

  • 前端開發(fā)日?qǐng)?bào):canvas獲取video縮略和JS 模塊化

    摘要:明白模塊化模塊化就是將一個(gè)大的功能拆分為多個(gè)塊,每一個(gè)塊都是獨(dú)立的,你不需要去擔(dān)心污染全局變量,命名沖突什么的。目前最重要的應(yīng)用場(chǎng)景之一,就是在的握手階段,客戶端服務(wù)端利用算法交換對(duì)稱密鑰。 1、應(yīng)用canvas獲取video的縮略圖 發(fā)布視頻時(shí)候,經(jīng)常需要上傳同時(shí)上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個(gè)發(fā)布視頻動(dòng)態(tài)的功能,我第一反應(yīng)就想到了H5的標(biāo)簽vidio和canv...

    Acceml 評(píng)論0 收藏0
  • 前端開發(fā)日?qǐng)?bào):canvas獲取video縮略和JS 模塊化

    摘要:明白模塊化模塊化就是將一個(gè)大的功能拆分為多個(gè)塊,每一個(gè)塊都是獨(dú)立的,你不需要去擔(dān)心污染全局變量,命名沖突什么的。目前最重要的應(yīng)用場(chǎng)景之一,就是在的握手階段,客戶端服務(wù)端利用算法交換對(duì)稱密鑰。 1、應(yīng)用canvas獲取video的縮略圖 發(fā)布視頻時(shí)候,經(jīng)常需要上傳同時(shí)上傳視頻的縮略圖,近日,應(yīng)產(chǎn)品經(jīng)理的的要求,需要做一個(gè)發(fā)布視頻動(dòng)態(tài)的功能,我第一反應(yīng)就想到了H5的標(biāo)簽vidio和canv...

    CarterLi 評(píng)論0 收藏0
  • 前端開發(fā)周報(bào):JavaScript編程術(shù)語和web片優(yōu)化

    摘要:函數(shù)式編程術(shù)語大全函數(shù)式編程有許多優(yōu)點(diǎn),它也越來越流行了。然而,每個(gè)編程范式都有自己獨(dú)特的術(shù)語,函數(shù)式編程也不例外。作用域有兩種類似全局作用域和局部作用域。目前最重要的應(yīng)用場(chǎng)景之一,就是在的握手階段,客戶端服務(wù)端利用算法交換對(duì)稱密鑰。 1、JavaScript 函數(shù)式編程術(shù)語大全 函數(shù)式編程(FP)有許多優(yōu)點(diǎn),它也越來越流行了。然而,每個(gè)編程范式都有自己獨(dú)特的術(shù)語,函數(shù)式編程也不例外。...

    kbyyd24 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<