chenfei-hnu / Blog

个人整理的跟前端相关的文档 ( This is some front-end development related documentation )
9 stars 2 forks source link

前端中数据流相关 #59

Open chenfei-hnu opened 2 years ago

chenfei-hnu commented 2 years ago

Streams API允许JavaScript以编程的方式访问通过网络接收的数据流

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。 类型化数组(TypedArray)对象描述了一个底层的二进制数据缓冲区的一个类数组视图(view)

前端利用a标签导出Blob数据

const url = window.URL.createObjectURL(new Blob([data]));
const link = document.createElement("a");
link.style.display = "none";
link.href = url;
const urlName = "导出.xlsx";
link.setAttribute("download", urlName);
document.body.appendChild(link);
link.click();

使用getUserMedia使用者获取设备的授权

navigator.mediaDevices.getUserMedia({ video: true })
.then(mediaStream => {
  /* use the stream */
})
.catch(err => {
  /* handle the error */
})

取得MediaStream 后,我们还需要再取得当中的Track,之后才可以透过ImageCapture 来操作

let imageCapture;
navigator.mediaDevices.getUserMedia({ video: true })
  .then(mediaStream => {
    const videoTrack = mediaStream.getVideoTracks()[0];
    imageCapture = new ImageCapture(videoTrack);
  })
  .catch(err => {
    console.log(err)
  });

document.querySelector("button").addEventListener("click", function() {
  imageCapture.takePhoto().then(blob => {
    console.log(blob)
  });
})

grabFrame,它和 takePhoto 一样是撷取videoTrack 的影像,差别在于它回传的是ImageBitmap 物件,而这种物件的好处是可以直接拿来画在Canvas 上。

imageCapture.takePhoto().then(blob => {
  console.log(blob)
});

imageCapture.grabFrame().then(imageBitmap => {
  console.log(imageBitmap)
});

Blob 对象可以够过 createImageBitmap(blob) 来转换成ImageBitmap 对象

完整例子 https://codepen.io/max-lee/pen/RwgJmJp

<div>
  <button onclick="openCamera()">開啟鏡頭</button>
  <button onclick="capture()">擷取畫面</button>
</div>
<video></video>
<canvas></canvas>

var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var videoTrack;
var imageCapture;

// 開啟鏡頭
function openCamera() {
  navigator.mediaDevices
    .getUserMedia({ video: true })
    .then((stream) => {
      // 取得視訊軌並建立 imageCapture
      videoTrack = stream.getVideoTracks()[0];
      imageCapture = new ImageCapture(videoTrack);
      // 將媒體流設定到 <video> 中顯示播放
      video.srcObject = stream;
      video.play();
    })
    .catch((err) => {
      console.log(err);
    });
}

//擷取畫面
function capture() {
  imageCapture
    .takePhoto()
    .then(blob => {
      // 將 Blob 轉成 ImageBitmap
      return createImageBitmap(blob)
    })
    .then(imageBitmap => {
      // 繪製在 canvas 上
      const { width, height } = imageBitmap;
      const ratio = video.videoWidth / width;
      canvas.setAttribute('width', width * ratio);
      canvas.setAttribute('height', height * ratio);
      context.drawImage(imageBitmap, 0, 0, width * ratio, height * ratio);
    });
}